17消息队列秒杀时如何处理每秒上万次的下单请求?
一开始 我们就了解了高并发系统的三个目标:高性能、高可用、易扩展。然后我们就讲解了分布式数据库改造、缓存的使用。究其原因我们遇到的大部分场景都是读多写少,尤其是在一个系统的初级阶段。
但是随着业务的发展,就会遇到一些高并发的请求场景,其中秒杀抢购就是最典型的场景,这个时候 我们面对的也是读多写少的场景,甚至是巨量的读场景。那么 有哪些措施可以应对呢?
因为用户查询的是少量的商品数据,属于热点查询,所以可以采用缓存策略尽量将请求挡在上层的缓存中,能被静态化的(图片,音频,视频)尽量静态化,这样就可以命中CDN节点,减少后端服务器的压力。
当然你也可以加上一些限流策略,比如短时间内对一个用户、一个ip、一台设备做重复请求丢弃处理。
秒杀开始,用户瞬间向系统发起请求订单,扣减库存,这些请求都是不经过缓存直接到达数据库的。1秒 1w个并发,系统的数据库濒临崩溃,寻找高并发的方案迫在眉睫。这是就想到了 消息队列。 消息队列
过去一直把消息队列看做暂时存储数据的一个容器,认为他是一个平衡低速系统和高速系统处理任务时间差的工具。
其实在一些组件中可以看到消息队列的影子: 在Java线程池中我们可以使用一个队列来存储暂时提交的任务,等待空闲线程池的处理 操作系统中断的下半部分也会使用工作队列来实现延后执行 我们再实现一个RPC框架的时候,也会将网络接受的请求写到任务队列里,再启动若干个工作线程来处理
总之,队列在系统设计是一个常用的组件 削去秒杀场景下的峰值写流量
秒杀场景下短时间数据库的写流量会很高,那么依照以前思路我们就可以通过分库分表来解决了。但是秒杀场景的写请求不是持续的,也就秒杀活动的那段时间存在,为了应对这一短暂场景而去花费时间扩缩容数据库时得不偿失的。
所以我们的思路是:将秒杀请求暂存在消息队列中,然后业务服务会响应用户 秒杀结果正在计算中,释放了系统资源再处理其它用户的请求。
我们会在后台启动若干个队列处理程序消费消息队列中的消息,再执行校验库存、下单等逻辑。因为只有有限个队列线程在执行,所以落入后端数据库上的并发请求是有限的。消息在队列中可以堆积,当库存消耗完毕,队列中的请求就可以被丢弃了。
这就是消息队列在秒杀中的主要作用,削峰填谷。当然我们可以根据队列积压的长度 来决定是否需要增加下游处理速度。
因为用户的等待也是有限度的。 通过异步处理简化秒杀请求中的业务流程
其实在大量的写请求"攻击"你的电商系统的时候,消息队列除了发挥主要的削峰填谷的作用之外,还可以实现 异步处理 来简化秒杀请求中的业务流程,提升系统的性能。
你想,在刚才提到的秒杀场景下,我们在处理购买请求时需要 500ms。这时你分析了一下整个的购买流程, 发现这里面会有主要的业务逻辑,也会有次要的业务逻辑 :比如说,主要的流程是生成订单、扣减库存;次要的流程可能是我们在下单购买成功之后会给用户发放优惠券,会增加用户的积分。
解耦实现秒杀系统模块之间松耦合
异步处理、解耦合和削峰填谷是消息队列在秒杀系统设计中起到的主要作用,其中异步处理可以简化业务流程中的步骤,提升系统性能;削峰填谷可以削去到达秒杀系统的峰值流量,让业务逻辑的处理更加缓和;解耦合可以将秒杀系统和数据系统解耦开,这样两个系统的任何变更都不会影响到另一个系统,
如果你的系统想要提升写入性能实现系统的低耦合,想要抵挡高并发的写流量,那么你就可以考虑使用消息队列来完成。