一. 加锁
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。
也可以解决:
Lua脚本是类似Redis事务,有一定的原子性,不会被其他命令插队,可以完成一些Redis事务性的操作。这点是关键。
知道原理了,我们就写一个脚本把判断库存扣减库存的操作都写在一个脚本丢给Redis去做,那到0了后面的都Return False了是吧,一个失败了你修改一个开关,直接挡住所有的请求,然后再做后面的事情嘛。
三. 放消息队列里
1. 单体或者集群Redis
把所有的请求放到Redis队列中,然后开启
1. 据说小米的解决方案:(不立即操作)
大家先发起抢的请求,服务器端把请求按先到先存规则放进消息队列,当消息队列到了最大值就说明是理论上的抢完了, 这时再处理消息队列生成订单, 大家过几分钟就能发现有没有抢得到, 抢到的让他们继续付款。
(PS:这里开启一个或者多个线程出队)
原文:https://www.cnblogs.com/yaopengfei/p/12418229.html