秒杀场景下超卖问题解决方案

本贴最后更新于 2029 天前,其中的信息可能已经时移世改

问题域一定要把握好。今天有人问到我“秒杀场景下超卖问题怎么解决”,我立马把问题域扩大到“秒杀系统要怎么建设”,方向已经偏到十万八千里了,而我也不知道如何回答了。

秒杀超卖现象:在高并发下,多个线程并发更新库存,导致库存为负的情况。

我搜集了一些资料,整理了一下,秒杀可选方案主要有以下三种:

1. 悲观锁

悲观锁方案最容易理解:在更新库存期间加锁,不允许其它线程修改。

1.1 select xxx for update

优点:确保了线程安全。

缺点:高并发场景下会导致多个请求一直等待,数据库性能下降,系统的链接数上升,负载飙升,影响系统的平均响应时间,甚至会瘫痪。

1.2 文件锁

优点与 1.1 类似,缺点是磁盘 IO 开销会变大。

1.3 缓存锁

当用户 A 要修改某个 id 的数据时,把要修改的 id 存入缓存,若其他用户触发修改此 id 的数据时,读到 memcache 有这个 id 的值时,就阻止其它用户修改。

优点与缺点与 1.2,但总体效果要好于以上两种方案。如果缓存是独立的集群,还可以解决跨进程乐观锁处理不了的问题。

1.4 分布式锁

与 1.3 类似。

2. 乐观锁

使用带版本号的更新。每个线程都可以并发修改,但在并发时,只有一个线程会修改成功,其它会返回失败。

Redis 的 watch

3. FIFO 队列

通过 FIFO 队列,使修改库存的操作串行化。

Redis 的队列

优点:不需要在单独加锁(无论是悲观锁还是乐观锁)。
缺点:队列的长度是有限的,必须控制好,不然请求会越积越多。

4. 结论

总的来说,不能把压力放在数据库上,所以使用"select xxx for update"的方式在高并发的场景下是不可行的。FIFO 同步队列的方式,可以结合库存限制队列长,但是在库存较多的场景下,又不太适用。所以相对来说,我会倾向于选择:乐观锁/缓存锁/分布式锁的方式。

5. 参考文献

https://blog.csdn.net/maikelsong/article/details/53322942

https://www.aliyun.com/jiaocheng/808179.html

https://blog.csdn.net/b1303110335/article/details/81365347

  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    139 引用 • 441 回帖
  • 秒杀
    8 引用 • 3 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...