原文链接:"https://www.cnblogs.com/wt645631686/p/13199532.html
削去秒杀场景下的峰值写流量
而在秒杀场景下,高并发的写请求并不是持续的,也不是经常发生的,而只有在秒杀活动开始后的几秒或者十几秒时间内才会存在。为了应对这十几秒的瞬间写高峰,将秒杀请求暂存在消息队列中,然后业务服务器会响应用户“秒杀结果正在计算中”,释放了系统资源之后再处理其它用户的请求。
在后台启动若干个队列处理程序,消费消息队列中的消息,再执行校验库存、下单等逻辑。因为只有有限个队列处理线程在执行,所以落入后端数据库上的并发请求是有限的。而请求是可以在消息队列中被短暂地堆积,当库存被消耗完之后,消息队列中堆积的请求就可以被丢弃了。
这就是消息队列在秒杀系统中最主要的作用:削峰填谷,也就是说它可以削平短暂的流量高峰,虽说堆积会造成请求被短暂延迟处理,但是只要时刻监控消息队列中的堆积长度,在堆积量超过一定量时,增加队列处理机数量,来提升消息的处理能力就好了,而且秒杀的用户对于短暂延迟知晓秒杀的结果,也是有一定容忍度的。
这里需要注意一下,所说的是“短暂”延迟,如果长时间没有给用户公示秒杀结果,那么用户可能就会怀疑你的秒杀活动有猫腻了。所以,在使用消息队列应对流量峰值时,需要对队列处理的时间、前端写入流量的大小,数据库处理能力做好评估,然后根据不同的量级来决定部署多少台队列处理程序,这里要根据平均请求时间和商品秒杀总量来计算,设定处理机的数量。
比如你的秒杀商品有1000件,处理一次购买请求的时间是500ms,那么总共就需要500s的时间。这时,你部署10个队列处理程序,那么秒杀请求的处理时间就是50s,也就是说用户需要等待50s才可以看到秒杀的结果,这是可以接受的。这时会并发10个请求到达数据库,并不会对数据库造成很大的压力。
通过异步处理简化秒杀请求中的业务流程
还是刚才的秒杀场景下,我们在处理购买请求时,需要500ms。分析了一下整个的购买流程,发现这里面会有主要的业务逻辑,也会有次要的业务逻辑:比如说,主要的流程是生成订单、扣减库存;次要的流程可能是我们在下单购买成功之后会给用户发放优惠券,会增加用户的积分。
假如发放优惠券的耗时是50ms,增加用户积分的耗时也是50ms,那么如果我们将发放优惠券、增加积分的操作放在另外一个队列处理机中执行,那么整个流程就缩短到了400ms,性能提升了20%,处理这1000件商品的时间就变成了400s。如果我们还是希望能在50s之内看到秒杀结果的话,只需要部署8个队列程序就好了。
解耦实现秒杀系统模块之间松耦合
比如数据团队对你说,在秒杀活动之后想要统计活动的数据,借此来分析活动商品的受欢迎程度等等指标。这时需要将大量的数据发送给数据团队。
一个思路是:可以使用HTTP或者RPC的方式来同步地调用,也就是数据团队这边提供一个接口,我们实时将秒杀的数据推送给它,但是这样调用会有两个问题:
- 整体系统的耦合性比较强,当数据团队的接口发生故障时,会影响到秒杀系统的可用性。
- 当数据系统需要新的字段,就要变更接口的参数,那么秒杀系统也要随着一起变更。
这时可以考虑使用消息队列降低业务系统和数据系统的直接耦合度。
秒杀系统产生一条购买数据后,我们可以先把全部数据发送给消息队列,然后数据团队再订阅这个消息队列的话题,这样它们就可以接收到数据,然后再做过滤和处理了。解耦合之后,数据系统的故障就不会影响到秒杀系统了,同时,当数据系统需要新的字段时,只需要解析消息队列中的消息,拿到需要的数据就好了。