前言
本篇文章是从之前的文章抽离出来的秒杀业务中不超卖的实现方案汇总
之前文章有些乱,这里重新修改了发布!
Redis+MQ保证:可能最优的方案
- 秒杀业务前,将秒杀商品和库存信息缓存到
Redis
中。
- 在
Nginx
、Tomcat
等处通过令牌桶
进行限流处理【防止被打崩】。
- 请求到达服务方法后判定
商品售卖完成缓存
中是否存在当前商品,如果不存在继续往下。
- 对
Redis
中缓存的商品数量做decr
减1操作,如果小于0则将商品id加入商品售卖完成缓存
中。避免每次都往Redis请求。
- 如果Redis做
decr
后大于0,则进行秒杀。
- 将订单信息通过
MQ
异步下单,通知后续业务。
- 后续业务就是正常的建立订单等业务。
关于上述方案的几点说明
- 秒杀商品的信息可以优先加载到缓存中。
- 发现商品售卖完成后,在本地建立商品售卖完成的缓存,避免每次都将请求发送到Redis做判定。
- 不应该是获取Redis中某商品的库存,然后再判定下单,而是在Redis中减少库存后做判定。因为直接通过Java代码查看库存,判定库存,减少库存是不具有原子性的,除非加分布式锁,但是意义不大。
- 秒杀后通过MQ异步下单
- 防止超卖其实是Redis的单线程特性的功劳。
本方案中中间件为 Redis和MQ。 Redis防止超卖 MQ异步下单。
关于抢购结果同客户端的交互:
- 假如服务方法已经读取到秒杀售罄的标志,那么直接返回秒杀失败
- 假如Redis判定还有库存
- 方案1:返回给客户端的是一个轮询
Key
,客户端轮询
- 方案2:客户端同服务端建立长连接,服务端主动告知
- 为什么不是在有库存的时候立马告知商品抢购成功?因为不能保证插入订单这个过程100%成功。
结余
如果Redis是瓶颈,可以部署多台Redis的方案来增大IO。
骐骥一跃,不能十步。驽马十驾,功在不舍。