最新要闻
- 每日简讯:第一次看到水冷的RX 7900 XTX:漂亮得不像话
- 环球微头条丨新一代显卡危机 《传送门》光追性能实测:卡成1帧PPT、RTX 4090惨败
- 全球首款第二代骁龙8+2K直屏旗舰!iQOO 11今天发
- 一到冬天就黑屏!但是 大众好像根本就不打算管
- 天天微资讯!Arc显卡也能战未来 Intel新驱动实测:性能提升真打鸡血
- 大中华区立功 消息称马斯克将任命朱晓彤特斯拉全球CEO
- 热推荐:电动车生产基地杀到欧洲?比亚迪最新回应来了
- 天天日报丨无2D版!《阿凡达2》预售开启:平均票价68元 首映口碑好评爆棚
- 【世界新要闻】备受年轻人追捧的“网红餐厅”有多坑?不服不行
- 快播:实火!《阿凡达2:水之道》预售首日总票房突破千万
- 小米13系列发布会时间偷跑 最新售价信息曝光:3999/4999元起售
- 天天头条:中国石化又一次产出99.999%高纯度氢:每年2100吨
- 即时看!12306购票页面变了:已取消查验核酸弹窗
- 天天观热点:双11期间快递达42.7亿件 你的收到了吗?
- 【快播报】员工爆料奶茶店用过期原料 老板:事儿太多
- 【全球热闻】刘海屏iPhone用上灵动岛:越狱软件开发者推出“灵动刘海”
手机
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
票房这么火爆,如何请视障人士“看”一场电影?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
- 票房这么火爆,如何请视障人士“看”一场电影?
家电
大数据量、高并发业务怎么优化?(一)
博主这里的大数据量、高并发业务处理优化基于博主线上项目实践以及全网资料整理而来,在这里分享给大家
一. 大数据量上传写入优化
线上业务后台项目有一个消息推送的功能,通过上传包含用户id的文件,给指定用户推送系统消息
(资料图片仅供参考)
1.1 如上功能描述很简单,但是对于技术侧想要做好这个功能,保证大用户量(比如达到百万级别)下,系统正常运行,功能正常其实是需要仔细思考的,博主这里给出思路:
- 上传文件类型选择
通常情况下大部分用户都会使用excel文件,但是相比excel文件还有一种更加推荐的文件格式,那就是csv文件,相比excel文件它可以直接在记事本编辑,excel也可以打开cvs文件,且占用内存更少(画重点),对于上传的csv文件过于庞大,也可以采用流式读取,读一部分写一部分
- 消息推送成功与否状态保存
由于大批量数据插入是一个耗时操作(可能几秒也可能几分钟),所以需要保存批量插入是否成功的状态,在后台中可以显现出这条消息推送记录是成功还是失败,方便运营回溯消息推送状态
- 批量写入启不启用事务
博主这里给出两种方案利弊:
- 启用事务:好处在于如批量插入过程中,异常情况可以保证原子性,但是性能比不开事务低,在特大数据量下会明显低一个档次
- 不启用事务:好处就是写入性能高,特大数据量写入性能提升明显,但是无法保证原子性,但是对于已经批量插入的新增数据,只是会产生脏数据而已,在功能设计合理的情况下是不影响业务的,如下面第四点
综上:在大数据量下,我们要是追求极致性能可以不启用事务,具体选择也需各位结合自身业务情况
- 推送异常失败的消息处理
建议功能设计上,可以屏蔽对失败消息再进行操作,这样不需要再处理之前推送失败写入的脏数据,直接新增消息推送即可
1.2 批量写入代码优化
- jdbc参数携带
rewriteBatchedStatements=true
在jdbc驱动上启动批量写入功能,如下
spring.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/test_db?allowMultiQueries=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&rewriteBatchedStatements=true
- 启用
insert into table(id, name) values(1, "tom"),(2, "jack")
模式,建议一次写入个数不要太多,MySQL对于sql长度是有限制的,对于这种字段少的表,一次写入500 - 1000问题不大,字段多了需要降低这个写入量
insert into im_notice_app_ref(notice_id, app_id, create_time)values (#{item.noticeId}, #{item.appId}, #{item.createTime})
一般情况下大家都知道第二条优化,但是可能会忽略jdbc参数携带rewriteBatchedStatements=true
,这个参数能在第二条的基础上启用批量执行SQL,进一步提升写入性能
二. 大事务优化,减小影响范围,提升系统处理能力
@Transactional
大于 Spring
提供得事务注解,许多人都知道,但是在高并发下,不建议使用,推荐通过编程式事务来手动控制事务提交或者回滚,减少事务影响范围
如下是一段订单超时未支付回滚业务数据得代码,采用 @Transactional
事务注解
@Transactional(rollbackFor = Exception.class)public void doUnPaidTask(Long orderId) { // 1. 查询订单是否存在 Order order = orderService.getById(orderId); if (order == null) { throw new BusinessException(String.format("订单不存在,orderId:%s", orderId)); } if (order.getOrderStatus() != OrderStatusEnum.ORDER_PRE_PAY.getOrderStatus()) { throw new BusinessException(String.format("订单状态错误,order:%s", order)); } // 2. 设置订单为已取消状态 order.setOrderStatus((byte) OrderStatusEnum.ORDER_CLOSED_BY_EXPIRED.getOrderStatus()); order.setUpdateTime(new Date()); if (!orderService.updateById(order)) { throw new BusinessException("更新数据已失效"); } // 3.商品货品数量增加 LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(OrderItem::getOrderId, orderId); List orderItems = orderItemService.list(queryWrapper); for (OrderItem orderItem : orderItems) { if (orderItem.getSeckillId() != null) { // 秒杀单商品项处理 Long seckillId = orderItem.getSeckillId(); SeckillService seckillService = SpringContextUtil.getBean(SeckillService.class); if (!seckillService.addStock(seckillId)) { throw new BusinessException("秒杀商品货品库存增加失败"); } } else { // 普通单商品项处理 Long goodsId = orderItem.getGoodsId(); Integer goodsCount = orderItem.getGoodsCount(); if (!goodsDao.addStock(goodsId, goodsCount)) { throw new BusinessException("秒杀商品货品库存增加失败"); } } } // 4. 返还优惠券 couponService.releaseCoupon(orderId); log.info("---------------订单orderId:{},未支付超时取消成功", orderId);}
采用编程式事务对其优化,代码如下:
@Resourceprivate PlatformTransactionManager platformTransactionManager;@Resourceprivate TransactionDefinition transactionDefinition;public void doUnPaidTask(Long orderId) { // 启用编程式事务 // 1. 在开启事务钱查询订单是否存在 Order order = orderService.getById(orderId); if (order == null) { throw new BusinessException(String.format("订单不存在,orderId:%s", orderId)); } if (order.getOrderStatus() != OrderStatusEnum.ORDER_PRE_PAY.getOrderStatus()) { throw new BusinessException(String.format("订单状态错误,order:%s", order)); } // 2. 开启事务 TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition); try { // 3. 设置订单为已取消状态 order.setOrderStatus((byte) OrderStatusEnum.ORDER_CLOSED_BY_EXPIRED.getOrderStatus()); order.setUpdateTime(new Date()); if (!orderService.updateById(order)) { throw new BusinessException("更新数据已失效"); } // 4. 商品货品数量增加 LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(OrderItem::getOrderId, orderId); List orderItems = orderItemService.list(queryWrapper); for (OrderItem orderItem : orderItems) { if (orderItem.getSeckillId() != null) { // 秒杀单商品项处理 Long seckillId = orderItem.getSeckillId(); SeckillService seckillService = SpringContextUtil.getBean(SeckillService.class); RedisCache redisCache = SpringContextUtil.getBean(RedisCache.class); if (!seckillService.addStock(seckillId)) { throw new BusinessException("秒杀商品货品库存增加失败"); } redisCache.increment(Constants.SECKILL_GOODS_STOCK_KEY + seckillId); redisCache.deleteCacheSet(Constants.SECKILL_SUCCESS_USER_ID + seckillId, order.getUserId()); } else { // 普通单商品项处理 Long goodsId = orderItem.getGoodsId(); Integer goodsCount = orderItem.getGoodsCount(); if (!goodsDao.addStock(goodsId, goodsCount)) { throw new BusinessException("秒杀商品货品库存增加失败"); } } } // 5. 返还优惠券 couponService.releaseCoupon(orderId); // 6. 所有更新操作完成后,提交事务 platformTransactionManager.commit(transaction); log.info("---------------订单orderId:{},未支付超时取消成功", orderId); } catch (Exception e) { log.info("---------------订单orderId:{},未支付超时取消失败", orderId, e); // 7. 发生异常,回滚事务 platformTransactionManager.rollback(transaction); }}
可以看到采用编程式事务后,我们将查询逻辑排除在事务之外,减小了其影响范围,也就提升了性能,在高并发场景下,性能优先的场景,我们甚至可以考虑不适用事务
三. 客户端海量日志上报优化
线上项目客户端,采用tcp协议与日志采集服务建立连接,上报日志数据。业务高峰期下,会有同时成千个客户端建立连接实时上报日志数据
如上场景,高峰期下,对日志采集服务会造成不小的压力,处理服务处理不当,会造成高峰期下,服务卡顿、CPU占用过高、内存溢出等。
这里给出海量日志高并发下优化点:
- 上报日志进行异步化处理,
- 普通版:采用阻塞队列
ArrayBlockingQueue
得生产者消费者模式,对日志数据进行异步批量处理,在此场景下,通过生产者将数据缓存再内存中,然后再消费者中批量保存入库。 - 进阶版:采用
Disruptor
队列,也是基于内存队列的生产者消费者模型,消费速度对比ArrayBlockingQueue
有一个数量级得性能提升,附简介说明:https://www.jianshu.com/p/bad7b4b44e48 - 终极版:采用
kfaka
消息队列中间件,持久日志数据,慢慢消费。虽然引入第三方依赖会增加系统复杂度,但是相比kfaka
在大数据场景下提供的优秀表现,这一点也是值得。
如上三种方案:大家可以结合自身项目实际体量选择
- 采集日志压缩
对上报后的日志如果要再发送给其他服务,推荐是对其进行压缩处理,避免消耗过多网络带宽以及最终数据落库选型:
- 网络传输,在
Java
里通常是指序列化方式,Jdk
自带得序列化方式对比Protobuf、fst、Hession
等在序列化速度和大小的表现上都没有优势,甚至可以用垃圾形容,博主这里直接给出Java
得几种序列化方式对比链接:https://segmentfault.com/a/1190000039934578,建议对传输大小要求较高可以使用Avro
序列化, 对综合要求较高可采用Protobuf
- 落库选型,像日志这种大数据量落库,都是新增且无修改得场景建议使用
Clickhouse
进行存储,相同数据量下对比MySql
占用存储更少,查询性能更高
最后,附博主 github
地址:https://github.com/wayn111
欢迎大家点赞、收藏、转发,你的支持将是博主更文的动力
大数据量、高并发业务怎么优化?(一)
每日简讯:第一次看到水冷的RX 7900 XTX:漂亮得不像话
环球微头条丨新一代显卡危机 《传送门》光追性能实测:卡成1帧PPT、RTX 4090惨败
全球首款第二代骁龙8+2K直屏旗舰!iQOO 11今天发
一到冬天就黑屏!但是 大众好像根本就不打算管
天天快资讯:python中的函数进阶
实时焦点:C++入门级基础知识汇总
天天微资讯!Arc显卡也能战未来 Intel新驱动实测:性能提升真打鸡血
大中华区立功 消息称马斯克将任命朱晓彤特斯拉全球CEO
当前最新:JavaWeb三大组件(Servlet、Filter、Listener)
世界报道:蓝牙协议(HFP、HSP、A2DP、AVRCP)简介
大前端html基础学习04--文本溢出
热推荐:电动车生产基地杀到欧洲?比亚迪最新回应来了
天天日报丨无2D版!《阿凡达2》预售开启:平均票价68元 首映口碑好评爆棚
【世界新要闻】备受年轻人追捧的“网红餐厅”有多坑?不服不行
环球即时:Springboot处理跨域请求
shell编程时出现:未预期的符号 `then' 附近有语法错误 或者 : 行 : `then'
世界最新:CSS Margin中5个经典布局解决方案,重难点知识,记得收藏复习
快播:实火!《阿凡达2:水之道》预售首日总票房突破千万
小米13系列发布会时间偷跑 最新售价信息曝光:3999/4999元起售
天天头条:中国石化又一次产出99.999%高纯度氢:每年2100吨
即时看!12306购票页面变了:已取消查验核酸弹窗
天天观热点:双11期间快递达42.7亿件 你的收到了吗?
【快播报】员工爆料奶茶店用过期原料 老板:事儿太多
【全球热闻】刘海屏iPhone用上灵动岛:越狱软件开发者推出“灵动刘海”
路怒可怕!出租车插队未果隧道逼停保时捷 还质问开豪车了不起:罚600扣1分
节省1000元成本 特斯拉减配辅助停车的超声波雷达:把新车主们坑惨了
暴雪《魔兽世界》停服或致大量游戏工作室倒闭:代打行业寒冬
加绒款同价:361° 纯色卫衣/运动裤69元大促(40元券)
Intel晒新显卡驱动表现:DX9游戏性能提升达80%
每日快播:一键部署应用到远程服务器,IDEA 官方 Docker 插件太顶了!
Vue视频 | 【Vue2 + Vue3 前端教程】完整版
今日关注:记录--微信小程序获取用户信息的最新方法记录
当前短讯!12 虚拟机字节码执行引擎_字节码执行机制
CompletableFuture源码解析
全球限量5000台!ThinkPad X1 Carbon 30周年纪念版即将上市
最新资讯:老马也失蹄 吞剑大师嘴插5把剑出意外被刺穿内脏:宣布收山
NASA毅力号火星车和国际空间站上的SSD:出自群联之手
网友不知情下话费暴涨2倍至99元 客服:一般会提前通知
每日快讯!Redis配置、优化及相关命令
《阿凡达》为何时隔13年推出续作?卡梅隆回应:光剧本就写了4版
全球时讯:纯电越野车真香!奇瑞也来参一脚:邀网友共创、最多奖励5万
每日视讯:一天1500元 索赔77万元代步车费用!博主曝特斯拉“精彩”上诉状
黄牛栽了!急于出手RTX 4080
两轮电动车在印度卷起来了:5年/6万公里质保、1年免费充电
Power BI 15 DAY
【高精密时钟】NTP网络校时服务器在WIN平台下调试步骤
微头条丨Chatgpt注册全流程教程
KMP算法详解-字符串匹配
焦点信息:精美的web前端源码的特效
天天短讯!女子连续服用6片感冒药致肝衰竭 专家提醒:药不能随便吃
男子被狗舔伤口发视频炫耀狗子贴心:听网友劝后打狂犬疫苗
全球播报:乐视诉清华大学获赔:内网提供电影下载 7年前就关停了
国服腾讯、网易等谁来代理?暴雪《暗黑4》发售时间曝光:容量80GB
环球动态:男子醉驾撞树想溜 爱车自动报警 并发送了定位
全球热点!JS设计模式 之 发布-订阅模式
最近沉迷Redis网络模型,无法自拔!终于知道Redis为啥这么快了
热点聚焦:行为管理(锐捷行业网关篇)
全球时讯:文盘Rust -- r2d2 实现redis连接池
前端精准测试实践
世界速递!JavaScript中 FileReader 对象详解
【世界报资讯】大数据-数据仓库-实时数仓架构分析
热头条丨JAVA8 函数式编程(1)- Lambda表达式
易基因|m6A去甲基化酶ALKBH5通过降低PHF20 mRNA甲基化抑制结直肠癌进展 | 肿瘤研究
焦点日报:火山引擎 DataTester:如何用 A/B 测试做产品增长?
WTM+InfluxDB时序数据库数据查询并放到DataTable中
中科慧政 & JNPF :全面开启智慧政务,灵活满足政务办公需求
【焦点热闻】南墙WAF-最好的免费Web应用防火墙
天天关注:高光时刻 | 方正璞华联合开发的「人力资源法律服务共享平台」在创新创业大赛中获奖
全球新消息丨95年属猪的2019年运势
【环球热闻】绳责的意思(绳责)
天天动态:水滴筹标题范文(水滴筹标题怎么写)
今头条!应用昆虫学(应用昆虫学报)
环球头条:工厂找哪个网站?
焦点信息:促排卵期间注意哪些事项(促排卵期间注意事项)
天天资讯:越南旅游签证办理流程及费用(越南旅游签证办理流程)
全球快报:空鼻症是什么样(空鼻症是什么病)
【天天新视野】电脑桌面怎么恢复到原来的样子(电脑桌面怎么恢复到原来的样子)
每日信息:闲鱼卖二手
微资讯!西藏万隆虫草鹿鞭王
环球观焦点:77电玩城(77dizhi)
热头条丨低温性能革命性进步!宁德时代:钠电池有望装车500公里续航车型
当前播报:非典是哪一年一共死多少人(非典是哪一年)
天天热讯:空调显示屏上显示df是什么意思(空调运行中显示屏出现字母df是什么意思)
全球报道:我国现存新能源汽车相关企业56.8万家,仅2021年新增17万家
全球要闻:日本电子巨头罗姆将量产下一代半导体:提高用电效率、增加电动车续航里程
环球今日报丨传感器和处理器如何打造更智能、更自主的机器人?
世界即时:如何实现工业自动化?传感器对于工业自动化有什么样的意义
天天新动态:工业自动化如何实现?
当前焦点!使用cpolar(内网穿透)最低成本搭建网站
如何在Windows AD域中驻留ACL后门
当前热点-灵感来自微信:微软计划开发一站式“超级应用”
环球即时看!惊险!SUV被货车顶上铁轨 火车驶来瞬间逃离
玩家们都嫌太贵!曝英伟达考虑将RTX 4080降价
世界讯息:AI生成裸照谁之过?真相恐怕和你想的不一样
3小时超值!《阿凡达2》电影票价普遍低于50元 IMAX版80元
Redis 的 keys 命令你知道有多慢吗?
“抽烟哥”红到国外 田协紧急倡议应积极正向:全马冲进3个半小时是狠人
世界百事通!RTX 4080全球销售疲软:太贵了我再等等
《阿凡达2》伦敦首映式