Redian新闻
>
一次线上事故,我顿悟了异步的精髓

一次线上事故,我顿悟了异步的精髓

公众号新闻

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 
来源:勇哥java实战分享

前言

在高并发的场景下,异步 是一个极其重要的优化方向。

前段时间,生产环境发生一次事故,笔者认为事故的场景非常具备典型性

写这篇文章,笔者想和大家深入探讨该场景的架构优化方案。希望大家读完之后,可以对异步 有更深刻的理解。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

1 业务场景

老师登录教研平台,会看到课程列表,点击课程后,课程会以视频的形式展现出来。

访问课程详情页面,包含两个核心动作:

  1. 读取课程视频信息 :

    从缓存服务器 Redis 获取课程的视频信息 ,返回给前端,前端通过视频组件渲染。

  2. 写入课程观看行为记录 :

    当教师观看视频的过程中,浏览器每隔3秒发起请求,教研服务将观看行为记录插入到数据库表中。而且随着用户在线人数越多,写操作的频率也会指数级增长。

上线初期,这种设计运行还算良好,但随着在线用户的增多,系统响应越来越慢,大量线程阻塞在写入视频观看进度表上的 Dao 方法。上。

首先我们会想到一个非常直观的方案,提升写入数据库的能力

  1. 优化 SQL 语句;
  2. 提升 MySQL 数据库硬件配置 ;
  3. 分库分表。

这种方案其实也可以满足我们的需求,但是通过扩容硬件并不便宜,另外写操作可以允许适当延迟和丢失少量数据,那这种方案更显得性价比不足。

那么架构优化的方向应该是:“减少写动作的耗时,提升写动作的并发度” , 只有这样才能让系统更顺畅的运行。

于是,我们想到了第二种方案:写请求异步化

  • 线程池模式
  • 本地内存 + 定时任务
  • MQ 模式
  • Agent 服务 + MQ 模式

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

2 线程池模式

2014年,笔者在艺龙旅行网负责红包系统相关工作。运营系统会调用红包系统给特定用户发送红包,当这些用户登录 app 后,app 端会调用红包系统的激活红包接口 。

激活红包接口是一个写操作,速度也比较快(20毫秒左右),接口的日请求量在2000万左右。

应用访问高峰期,红包系统会变得不稳定,激活接口经常超时,笔者为了快速解决问题,采取了一个非常粗糙的方案:

"控制器收到请求后,将写操作放入到独立的线程池中后,立即返回给前端,而线程池会异步执行激活红包方法 "。

坦率的讲,这是一个非常有效的方案,优化后,红包系统非常稳定。

回到教研的场景,见下图,我们也可以设计类似线程池模型的方案:

使用线程池模式,需要注意如下几点:

1、线程数不宜过高,避免占用过多的数据库连接 ;

2、需要考虑评估线程池队列的大小,以免出现内存溢出的问题。

3 本地内存 + 定时任务

开源中国统计浏览数的方案非常经典。

用户访问过一次文章、新闻、代码详情页面,访问次数字段加 1 , 在 oschina 上这个操作是异步的,访问的时候只是将数据在内存中保存,每隔固定时间将这些数据写入数据库。

示例代码如下:

我们可以借鉴开源中国的方案 :

  1. 控制器接收请求后,观看进度信息存储到本地内存 LinkedBlockingQueue 对象里;
  2. 异步线程每隔1分钟从队列里获取数据 ,组装成 List 对象,最后调用 Jdbc batchUpdate 方法批量写入数据库;
  3. 批量写入主要是为了提升系统的整体吞吐量,每次批量写入的 List 大小也不宜过大 。

这种方案优点是:不改动原有业务架构,简单易用,性能也高。该方案同样需要考虑内存溢出的风险。

4 MQ 模式

很多同学们会想到 MQ 模式 ,消息队列最核心的功能是异步解耦 ,MQ 模式架构清晰,易于扩展。

核心流程如下:

  1. 控制器接收写请求,将观看视频行为记录转换成消息 ;

  2. 教研服务发送消息到 MQ  ,将写操作成功信息返回给前端 ;

  3. 消费者服务从 MQ 中获取消息 ,批量操作数据库 。

这种方案优点是:

  • MQ 本身支持高可用和异步,发送消息效率高 , 也支持批量消费;
  • 消息在 MQ 服务端会持久化,可靠性要比保存在本地内存高;

不过 MQ 模式需要引入新的组件,增加额外的复杂度。

5 Agent 服务 + MQ 模式

互联网大厂还有一种常见的异步 的方案:Agent 服务 + MQ 模式。

教研服务器上部署 Agent 服务(独立的进程) , 教研服务接收写请求后,将请求按照固定的格式(比如 JSON )写入到本次磁盘中,然后给前端返回成功信息。

Agent 服务会监听文件变动,将文件内容发送到消息队列 , 消费者服务获取观看行为记录,将其存储到 MySQL 数据库中。

还有一种演进,假设我们不想在应用中依赖消息队列,不生成本地文件,可以采用如下的方式:

这种方案最大的优点是:架构分层清晰,业务服务不需要引入 MQ 组件。

笔者原来接触过的性能监控平台,或者日志分析平台都使用这种模式。

6 总结

学习需要一层一层递进的思考。

第一层:什么场景下需要异步

  • 大量写操作占用了过多的资源,影响了系统的正常运行;
  • 写操作异步后,不影响主流程,允许适当延迟;

第二层:异步的外功心法

本文提到了四种异步方式:

  • 线程池模式

  • 本地内存 + 定时任务

  • MQ 模式

  • Agent 服务 + MQ 模式

它们的共同特点是:将写操作命令存储在一个池子后,立刻响应给前端,减少写动作的耗时。任务服务异步从池子里获取任务后执行。

第三层:异步的本质

在笔者看来,异步是更细粒度的使用系统资源的一种方式

在教研课程详情场景里,数据库的资源是固定的,但写操作占据大量数据库资源,导致整个系统的阻塞,但写操作并不是最核心的业务流程,它不应该占用那么多的系统资源。

我们使用异步的解决方案时,无论是使用线程池,还是本地内存 + 定时任务 ,亦或是 MQ ,对数据库资源的使用都需要在合理的范围内,只有这样系统才能顺畅的运行。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
被拒800次的张颂文让我顿悟,什么才是高层次的快乐看完上百个家庭的育儿血泪史,我顿悟了“推娃真谛”!和家长打交道多了,我顿悟了一个越来越强烈的教育真相2元退烧药刷屏之后,我顿悟了一种“高智商的善良”从月薪5000到年入100万,我顿悟了这世上最隐蔽的一条潜规则被拒800次的张颂文让我顿悟,什么是高层次的快乐看完《三体》,我顿悟了5个最残酷的职场生存法则是枝裕和《舞伎家的料理人》曝正式预告,日本文化的精髓是什么?日增阳性100万!浙江这个数据,让我顿悟了这几个真相……阳过第一个春节,我顿悟以前都把年过反了美国文化中的感恩与赦免(原谅)新疆大火看了星云大师的故事,我顿悟了这个成功真相看了宁波教师“淘汰”机制,我顿悟什么才是后疫情时代的生存法则人到中年读书会-朱自清散文《吃的》读过《杨绛传》我顿悟,成熟是从摆脱内耗开始的刘强东痛骂京东高管,拿PPT骗自己:我顿悟了这条职场铁律实现异步的方式,你知道几个?读了罗翔《法治的细节》,我顿悟人这一生,为何要读很多的书读懂范仲淹《岳阳楼记》我顿悟:没有一种人生不辛苦,熬过去在美国312.老人悲凉、无家可归哥大教授专访:文理学院有多重要?它是美国教育最引以为豪的精髓!看了世界杯巨星的成长史,我顿悟寒门子弟逆袭的底层逻辑腾讯35岁设计师真实工资大曝光,我顿悟了成人社会的残酷规则!看完郭晶晶豪门鸡娃,我顿悟:有没有一种可能,中产的内卷做得都是无用功?腾讯35岁员工高调离职!真实工资大曝光,我顿悟了成人社会的残酷规则!“国民媳妇”海清患病细节罕见曝光,我顿悟什么才是最高级的自律看完郭晶晶豪门鸡娃的我顿悟了:原来中产拼了命的内卷都是无用功?对话宝马董事长齐普策:数字化的精髓在于客户体验老钱风的精髓真的不是“钱”看了孙俪的新年礼物,我顿悟:为什么过年一定要给孩子仪式感?为什么蒋万安成功当选?雷军20年前的这句话,让我顿悟:真正厉害的人,根本不会选“先搞起来再说”看了北大灌饼父亲,我顿悟:富养不如穷养,穷养不如安养,安养不如教养蚂蚁:实现异步的8种方式,你知道几个?
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。