如何设计一个能抗高并发的秒杀场景
Posted wen-pan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何设计一个能抗高并发的秒杀场景相关的知识,希望对你有一定的参考价值。
说明:秒杀场景中有许多需要考虑的问题,这里只是将如何设计一个能抗高并发的秒杀设计的主流程进行分析!!!
一、秒杀的特点
- 商品库存总量固定
- 先到先得,瞬时并发极大
- 商品数量和库存数量有限
二、如何设计秒杀场景
1. 秒杀开始前先将秒杀的商品和对应的库存预热到Redis中(商品code : 对应的库存)
2. 秒杀开始,大量用户开始点击按钮进行秒杀
3. nginx对用户请求进行过滤,通过执行lua脚本去Redis中扣减对应商品的库存(预减库存)
- 如果库存扣减成功则继续放行请求到网关
- 如果扣减库存失败,则直接返回个前端
秒杀失败
的响应
4 .网关将请求转发到后台的应用服务
5. 应用服务收到请求后,根据请求中的商品id和用户信息生成一个秒杀消息
并将消息投递到MQ中
6. 订单服务去订阅MQ中这个队列,将秒杀消息取出
7. 根据秒杀消息生成一条订单信息存入到mysql数据库,到这里订单生成就完毕了
8. 秒杀成的客户端需要提供一个定时查询订单状态的功能,一旦订单生成成功了,则客户端就可以点击查看订单详情,然后去支付了
三、设计上的优点
- 利用预减库存方案杜绝超卖
- 利用NGINX + lua在网关层面就将无效请求阻挡(防止大流量冲击)
- 利用MQ消息队列的限流特性保证了MySQL不会被瞬时流量击垮
- 这里MQ可以设置每次推送给消费者的数量(比如每次推送500条消息,而不是每次全部一起推送),从而让MySQL不会被瞬时的流量击垮
- APP需要额外的设计轮询机制查询订单的状态
四、相关问题
1、订单创建后,用户长时间不支付,或用户主动订单取消怎么办
- 如果是用户主动取消订单,那么我们需要提供一个接口用于用户取消时恢复该商品的库存量,这个比较简单,一般是采用lua脚本去将商品库存量+1
- 如果是订单长时间不支付(比如我们设置如果订单超过30分钟不支付就自动过期),我们也需要释放该订单占用的库存量。这种情况要稍微麻烦一点,主要是如何筛选出超过三十分钟仍未支付的订单?
- 如果直接通过定时任务去定时查询数据库,查询出支付状态为
未支付
且订单创建时间超过三十分钟的订单,然后修改订单状态为取消并且释放占用的库存量。这种方案在订单数量不是很大的小项目可行。但是如果在某些单量很大的项目中,这种操作对数据库的压力很大。不是一个很好的解决方案!
- 如果直接通过定时任务去定时查询数据库,查询出支付状态为
2、秒杀接口如何限流防刷
如何防止用户恶意刷秒杀接口
3、秒杀开始前如何隐藏接口
我们的秒杀地址在秒杀开始前一般不会暴露出去的,并且在秒杀的时候需要隐藏我们的秒杀地址,防止有人绕过前端js验证恶意刷接口。
4、如何防止一个用户多次秒杀
某些秒杀场景中需要限制一个用户对一件商品只能进行一次秒杀,如何防止用户多次秒杀呢?
以上是关于如何设计一个能抗高并发的秒杀场景的主要内容,如果未能解决你的问题,请参考以下文章