一. 加锁
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: 这里开启一个或者多个线程出队)
来源: http://www.bubuko.com/infodetail-3447887.html