秒杀如何防止库存超卖?
未标记
考查重点:原子扣减与购买约束。原子条件扣权威库存并事务建单,重试/消费幂等,购买唯一约束兜底,不能先查再无条件扣
本题目录
参考答案
核心回答
防止秒杀超卖,关键是在权威库存中原子地完成“检查足够并扣减”,让扣库存与创建订单保持事务一致,并防止重试和消息重复造成多次扣减。仅仅先查库存大于零、随后再减一,会产生并发竞争。
以 MySQL 8.4 InnoDB 管理最终库存和订单为例:
- 扣减时在更新条件中要求库存不少于本次购买量,并检查实际影响行数;扣减失败就不能创建成功订单。也可以在事务内先锁定库存行,再检查与扣减。
- 扣库存、订单或预占记录在同一事务内提交,失败一起回滚。请求使用稳定业务标识,避免超时重试再次扣减。
- 流量大时,在入口限流,用
RedisLua原子预扣减少无效竞争,通过 MQ 异步处理订单;数据库仍保留最终约束。 - 对未支付超时、取消和失败建立状态机,按预占记录释放一次,处理重复消费、迟到消息和异常恢复。
Redis 与 MQ 是可选的承压手段,不能替代最终库存约束;一人一单则是另一条用户资格约束,需要相应业务唯一键和状态规则。
只剩一件时,数据库怎样避免竞态
如果两个请求都普通查询到库存为 1,再各自按这个旧值更新,就可能同时认为自己抢到商品。应把“库存足够”放进实际扣减的原子更新条件,或者在持有库存行锁的同一事务里完成检查和修改。
这样,一个事务成功扣完后,另一个请求执行扣减时必须根据受保护的当前状态判断,不能继续用之前查询到的 1。应用检查更新结果,只有扣减成功才推进订单;事务中途失败,则连同订单相关写入一起回滚。购买数量也要验证为合法正数,不能让负数购买反向增加库存。
如果使用版本号做乐观控制,也要同时验证库存足够,并处理更新失败;高竞争下无限重试只会继续放大负载。库存行的定位应有合适索引,事务尽量短,避免持锁期间远程调用支付等服务。
Redis 预扣和 MQ 各负责什么
Redis 中的检查与预扣应放在同一个短 Lua 脚本,避免应用把读取和修改拆成多次独立命令。MQ 把突发请求转为可控的后台处理速率,但队列有容量和保留边界,不能无限接收。
Redis 预扣成功不等于数据库订单已成功。预扣后进程崩溃、发送消息超时、消息重复、Redis 状态在故障切换中丢失,都需要恢复协议。应有可恢复的请求与待处理记录,按稳定标识重试投递和查询结果;发送超时可能只是确认没到,不能立即无条件补库存。
数据库扣减与订单事务仍是最终检查:即使 Redis 误放行,也不能突破最终额度。相应代价是预占被受理后仍可能失败,需要异步结果查询、失败通知与预占清理,不能在入口直接承诺最终成功。
重试、取消和多渠道库存怎样处理
同一订单消息可能在数据库提交后因确认失败再次投递,应识别已有业务结果,不能再扣一遍。数据库唯一约束可以防止重复订单,约束记录与扣减要在同一事务中;仅给请求换一个新 ID,就不能再视为同一次重试。
取消释放必须是有条件、一次性的状态转换:只有确实预占且尚未成功消耗或释放的额度才能返还。已支付订单不能被迟到的超时任务取消,重复取消也不能重复加库存。支付、取消和释放要协调各自允许的状态迁移。
如果多个销售入口、后台人工修改或多个活动共享同一批库存,它们必须遵守同一个库存规则;独立 Redis 计数器各自都不减成负数,也不代表总销量不会超额。需要分桶时,应先分配总和不超过可售库存的额度,并管理额度转移,不能凭空给每个桶一份完整库存。活动开始和恢复时还要对账预占、订单与可售量,发现异常及时限制继续受理。
参考资料
- 国内:JavaGuide:服务限流详解:用于解释入口承压与 Redis Lua 原子检查的作用,区分限流、预扣和最终库存安全。
- 国内:JavaGuide:接口幂等性设计详解:用于设计稳定业务标识、唯一约束及同事务的去重和扣减,防止重复订单和重复释放。
- 国内:阿里云:消息幂等:用于解释发送与确认失败后的重投,说明后台订单处理为什么仍需业务幂等。
- 国外:Redis:Scripting with Lua:用于核对脚本内条件检查和更新的原子执行,以及它不能覆盖其他系统事务的范围。
- 国外:MySQL 8.4:Locking Reads:用于解释共享计数记录为何不能先普通读再更新,以及锁定读取、更新和事务释放的关系。
相关面经
8 篇百度
Java开发秒杀场景如何避免超卖(不用redis)?
恒生电子
后端开发(Java)高并发本地生活项目防超卖的整体链路
小红书
电商有个热点福利品,库存几十万,会触发秒杀,你作为秒杀链路负责人,怎么设计优化整条链路保证高TPS?
科大讯飞、首都在线、宇量晟、四川长虹、度小满、字节跳动、恒生电子、腾娱互动、金蝶、汽车之家
面试官真是我实习面试,秋招面试以来最耐心,最和蔼的一个了,问的非结构化问题比较多,问了一些项目。重点围绕出现问题怎么解决,怎么排查。场景题比较多:库存超卖,高并发场景限流。面试官在我答完后会发表自己的见解,整场面试下来感觉是在和一个前辈交流,而不是被人拷打,夯爆了。当场给过了。
水滴
质量保障工程师(AI)数据库表中的一行是某商品的库存,只剩1了,有十多个人在抢这个货,会出现什么样的问题,如何去解决这个问题。



