vlambda博客
学习文章列表

秒杀系统中的扣减库存和流量削峰

01


前言


上篇文章我们一起讨论了秒杀系统下,通过堆加机器解决高并发的方案有什么缺点,又讨论了使用多级缓存架构构建静态化页面,来减轻前端页面服务器压力的方式。


今天我们就接着往下讨论,小伙伴们可以看一下上一篇文章做个复习,


我们先回顾一下场景。


假如我们的系统在00:00有一场秒杀活动,那么会有大量用户会提前几分钟开始刷新页面,这部分的解决方案上篇文章已经提出。


紧接着就是到了00:00之后,页面上可能会出现一个按钮,大量用户就会通过点击按钮开始向后台发送请求,抢购商品。


抢购到之后还要有下订单、支付、减库存等后续一系列的流程,所以不对这些操作进行优化,直接操作数据库,系统的压力一定是很大的。


接下来我们就针对这个问题一起看看如何解决吧。


02


验证用户身份


首先我们思考一个问题,对于秒杀活动,会不会有人作弊呢?


比如写好一段代码,在秒杀活动开始之前就不停的循环刷新页面,抢购商品。


王子告诉大家,这种情况是一定会发生的。其实我们看看各种抢票软件就明白了,每次高峰期抢票不也会有很多的渠道去刷票吗,这么看来12306能支持这么多的并发确实做得还不错。


那么如何针对这种作弊的行为呢,其实我们可以在秒杀成功之后做一个验证用户身份的功能,保证你是人而不是代码。


方式可以是弹出框做个验证码验证,或者做个答题功能,需要人工答对之后才能进行下一步的操作。


这个办法是非常有效的,不仅可以对作弊行为进行过滤,而且每个人回答的速度是不一样的,所以用户发起的请求就不会全部的积压在一个时间点上。


03


独立的秒杀系统集群


身份验证过后,用户就会把大量的请求发送到我们的订单系统中,那么问题来了,在秒杀活动中发起的海量请求,是要发给我们平时运行时使用的同一个订单系统集群中吗?


我们来思考一个问题,假如秒杀业务和平时的业务使用的是一套订单系统集群,那么在秒杀活动的时候,可能有海量的用户来参加秒杀活动,但是同样也有不会参加秒杀活动的用户在同时订购商品。


那么当秒杀开始的时候,订单服务器压力会剧增,普通用户也发起请求到订单服务器,这样会发生什么呢?


很可能服务器由于秒杀系统带来的压力,性能变差,那么普通用户在进行正常的下订单操作时也会发现系统运行缓慢。


所以我们要单独部署一套秒杀系统集群,单独处理秒杀业务,从而不影响正常业务的性能。


而且单独的秒杀系统集群也更容易做一些特殊的架构优化,说到这里,架构图如下:


04


扣减库存的优化


后台系统在用户抢购成功后,应该先做什么操作呢?


第一步操作就是扣减库存,因为大家知道,参与秒杀活动的商品都是有数量限制的,所以大量用户抢购成功后的第一步操作就是扣减库存。


那么如何进行扣减库存的操作呢?


小伙伴们可能会回答,可以在秒杀系统集群中调用库存系统接口,连接数据库,更新库存数量。但这样一来不就又面临着数据库压力过大的问题了吗?


其实我们可以在活动开始前,把要秒杀的商品库存存放到Redis集群中,然后扣减库存的时候只操作Redis集群,就可以大大降低数据库压力了。


当商品的库存扣减完毕之后,用户发送过来抢购的请求其实就不必再发送给秒杀系统了,可以直接在Nginx中过滤掉。


Nginx具体如何过滤呢?这里王子提出一点思路,我们可以通过Zookeeper来实现。


当商品库存为0后,我们可以在Zookeeper中设置一个标志,表名商品已经售空了,同时可以利用Zookeeper的监听机制,告知Nginx的lua脚本,然后Lua脚本直接过滤掉无效的请求,并返回用户一个“库存已售空”的响应信息就可以了。


这样可以很大幅度的减少海量请求对后台秒杀系统的压力。


05


引入RocketMQ进行流量削峰


通过之前的优化,已经过滤掉了大量的无用请求,那么针对正常参加秒杀,发送给后台的请求我们应该怎么进行架构优化呢?


这个时候我们就可以引入RocketMQ,来进行流量削峰了


也就是说,当用户发送请求,经过Redis扣减库存的操作后发现库存数量还是大于0的,那么这个时候就可以把创建订单的操作发送消息给RocketMQ,然后我们平时使用的订单系统从RocketMQ中限流获取消息,进行常规的操作(生成订单、支付等等)。这样就不会对数据库有太大的压力了。


由于订单系统限流获取消息,所以会造成RockeMQ的消息积压问题,但RocketMQ是高可用的集群,可以保证消息的不丢失。所以完全可以让订单系统每秒几千条的速度去消费,顶多可能会延迟个几十秒才会生成订单而已。


所以我们最后的架构图如下:


秒杀系统中的扣减库存和流量削峰

06


总结


到这里,相信小伙伴们对于秒杀系统的架构方案已经有了一个整体的了解了。


其实总结起来,秒杀系统的架构优化核心就是:单独部署抗下高并发的服务器集群,阻止高并发请求访问数据库


因为数据库是整个系统架构中的性能瓶颈,不可能无限扩展数据库服务器的数量来抗下高并发请求。而且不是所有时候系统都有这么高的并发的,扩展数据库并不划算。


还有在这里王子要说明一点,一套完整的秒杀系统架构体系是很复杂的,我们只是通过这么一个秒杀业务的场景,让小伙伴们感受到消息中间件在这样的架构中扮演的角色。


后续的文章里,我们还会一起深入的探讨消息中间件的底层原理,让我们一起进步吧。

 

往期文章推荐:

中间件专辑:




HUC思梦 发起了一个读者讨论 写留言