在高并发场景下,异步是一个极其重要的优化方向。前段时间,生产环境发生了意外。笔者认为,事故现场非常典型。写这篇文章,笔者想深入探讨一下针对该场景的架构优化方案。希望大家看完之后,能够对异步有更深的理解。1.业务场景当老师登录教研平台后,会看到课程列表。点击课程后,课程将以视频的形式展示。访问课程详情页面包括两个核心动作:读取课程视频信息:从缓存服务器Redis中获取课程视频信息,返回给前端,前端通过视频组件进行渲染。写入课程观看行为记录:老师在观看视频时,浏览器每3秒发起一次请求,教研服务将观看行为记录插入到数据库表中。并且随着在线用户数量的增加,写操作的频率会呈指数增长。上线之初,这种设计效果不错,但随着在线用户的增多,系统响应越来越慢,大量线程阻塞在写入视频观看进度表的道方法中。优越的。首先,我们会想到一个非常直观的方案来提高写入数据库的能力。优化SQL语句;改进MySQL数据库硬件配置;分库分表。这个方案其实可以满足我们的需求,但是扩展硬件的成本并不便宜。此外,写操作可以允许适当的延迟和少量的数据丢失,因此这种方案更具有成本效益。那么架构优化的方向应该是:“降低写操作的耗时,增加写操作的并发”,只有这样系统才能运行的更加流畅。于是,我们想到了第二种方案:异步写请求。线程池模式本地内存+定时任务MQ模式Agent服务+MQ模式2.线程池模式2014年,笔者在艺龙负责红包系统相关工作。操作系统会调用红包系统向特定用户发送红包。当这些用户登录app时,app会调用红包系统的激活红包接口。激活红包界面是写操作,速度比较快(20毫秒左右)。接口日请求量约2000万。在应用访问高峰期,红包系统会变得不稳定,激活界面经常会超时。为了快速解决问题,作者采用了一个很粗略的方案:“controller收到请求后,将写操作放到一个独立的线程池中完成,完成后立即返回前端,线程池会执行异步激活红包的方法”。当时按照这个粗略的方法优化后,红包系统非常稳定,再也没有出现界面响应超时的问题。回到教学科研场景,如下图,我们也可以设计一个类似线程池模型的方案:使用线程池模型,需要注意以下几点:线程数不宜太高,避免占用过多的数据库连接;我们需要考虑评估线程池队列的大小以避免内存溢出问题。3.本地内存+定时任务开源的中国统计浏览方案非常经典。用户访问过文章、新闻、代码详情页一次,访问次数字段自增1。这个操作在oschina上是异步的。访问时,数据只保存在内存中,这些数据每隔一定时间写入数据库。示例代码如下:我们可以借鉴开源中国的方案:controller收到请求后,将观看进度信息存储在本地内存的LinkedBlockingQueue对象中;异步线程每隔1分钟从队列中获取数据,组装成List对象,最后调用Jdbc的batchUpdate方法批量写入数据库;分批写入的主要目的是为了提高系统的整体吞吐量,每批写入的列表大小不宜过大。该方案的优点是不改变原有业务结构,简单易用,性能高。该方案还需要考虑内存溢出的风险。4.MQ模式很多同学都会想到MQ模式。消息队列的核心功能是异步和解耦。MQ模式结构清晰,易于扩展。核心流程如下:controller收到写入请求,将视频观看行为记录转化为消息;教研服务向MQ发送消息,并向前端返回写操作成功信息;消费服务从MQ获取消息,批量操作数据库。该方案的优点是:MQ本身支持高可用和异步,消息发送效率高,同时也支持批量消费;消息会持久化在MQ服务器上,可靠性高于本地内存;但是,MQ模式需要引入新的组件,增加了额外的复杂性。5、代理服务+MQ模式互联网巨头也有通用的异步解决方案:代理服务+MQ模式。Agent服务(独立进程)部署在教研服务器上。教研服务收到写入请求后,将请求以固定格式(如JSON)写入磁盘,然后返回成功信息给前端。Agent服务会监听文件的变化,将文件内容发送到消息队列,Consumer服务会获取浏览行为记录,存入MySQL数据库。该方案最大的优势在于架构层次清晰,业务服务无需引入MQ组件。笔者接触过的性能监控平台或者日志分析平台都采用这种模式。6、总结学习需要层层递进的思考。第一层:什么场景需要异步大规模写操作占用太多资源,影响系统的正常运行;异步写操作后,不影响主进程,允许适当延迟;第二层:异步对外技巧提到了四种异步方式:线程池方式本地内存+定时任务MQ方式代理服务+MQ方式。它们的共同特点是:将写操作命令存储在一个池中后,立即响应给前端,减少写操作的耗时。任务服务异步地从池中获取任务并执行它们。第三层:异步的本质在我看来,异步是一种更细粒度地使用系统资源的方式。在教研课详情场景中,数据库的资源是固定的,但是写操作占用了大量的数据库资源,导致整个系统阻塞,但是写操作不是核心业务流程,它应该不会占用那么多系统资源。不能为了异步而异步。无论是使用线程池,还是本地内存+定时任务,或者MQ,对数据库资源的使用都必须在一个合理的范围内,否则异步达不到预期的效果。
