https://www.cnblogs.com/yaopengfei/p/12418229.htmlhtml
一. 加锁redis
1. 单个IIS(即单进程),经过在代码里lock线程锁便可。数据库
2. 若是是IIS集群,多个IIS同时请求DB,那么lock线程锁就锁不住了,这里就须要引入Redis分布式锁,全部请求先去Redis加锁→秒杀→解锁,实际上多个IIS请求最终到数据库 依次前后进行的。服务器
这个时候,若是说Redis扛不住这个并发,搞Redis集群,Redis集群中的锁也是依次进行的,集群中必须上一个redis解锁,下一个才能加锁,因此这里引入Redis集群,是为了应对高并发问题,是为了防止redis宕机,并不能加快最终秒杀的速度,实际上和单体Redis速度是同样的。并发
二. 库存放redis里异步
1. 单体Redis没问题,提早把商品的库存加载到Redis中去,让整个流程都在Redis里面去作(利用Redis原子性),而后等秒杀介绍了,再异步的去修改库存就行了。分布式
2. 集群Redis有问题。高并发
好比如今库存只剩下1个了,咱们高并发嘛,4个redis服务器一块儿查询了发现都是还有1个,那你们都以为是本身抢到了,就都去扣库存,那结果就变成了-3。spa
也能够解决:线程
Lua脚本是相似Redis事务,有必定的原子性,不会被其余命令插队,能够完成一些Redis事务性的操做。这点是关键。
知道原理了,咱们就写一个脚本把判断库存扣减库存的操做都写在一个脚本丢给Redis去作,那到0了后面的都Return False了是吧,一个失败了你修改一个开关,直接挡住全部的请求,而后再作后面的事情嘛。
三. 放消息队列里
1. 单体或者集群Redis
把全部的请求放到Redis队列中,而后开启一个线程去 出队执行秒杀业务(秒杀业务执行完,下一个才出队),实际上到数据库仍是 一个接着一个进行。
注意: 若是是开多个线程出队执行秒杀业务, 或者 即便单线程出队,而后秒杀 ,出队和秒杀是分开执行, 一样会存在上一个秒杀业务没有执行完,下一个又进来了。
还要注意:若是秒杀业务是集群,即便是依次出队,打到DB上仍是会存在上述问题,且无法保证原先队列中的前后顺序了。
2. 听说小米的解决方案:(不当即操做)
你们先发起抢的请求,服务器端把请求按先到先存规则放进消息队列,当消息队列到了最大值就说明是理论上的抢完了, 这时再处理消息队列生成订单, 你们过几分钟就能发现有没有抢获得, 抢到的让他们继续付款。