1 万件商品,10 万人抢。库存扣成 -500 就是超卖,真金白银的损失。怎么防?
一、超卖根因
UPDATE stock SET num=num-1 WHERE id=1 在并发下,多个线程同时读 num=1,都扣成 0 后再减——变成负数。要"读-改-写"原子。
二、前端三道
-
按钮置灰,防重复点。 -
答题 / 验证码,削峰值。 -
静态资源 CDN,别打后端。
三、接入层
-
限流(网关/Nginx):超出阈值直接拒。 -
削峰:请求进 MQ,后端按能力消费。
四、应用层
- Redis 预扣库存
:库存放 Redis, DECR原子减,≤0 直接拒,不进 DB。 - 分布式锁 / Lua
:扣库存+下单 原子化。
五、数据库
- 乐观锁 / 行锁
: UPDATE stock SET num=num-1 WHERE id=1 AND num>=1,扣不动就失败,兜底防超卖。
六、面试速记
-
超卖 = 读改写不原子。 -
前端置灰 + 答题削峰。 -
网关限流 + MQ 削峰。 -
Redis 原子 DECR 预扣。 -
DB 用 num>=1条件兜底。 -
层层拦截,DB 是最后一道。
七、一句话带走
秒杀防超卖:前端削峰 → 网关限流 → MQ 削峰 → Redis 原子预扣 → DB 行锁兜底。八道防线层层拦,DB 只接它能扛的。
系统设计面试
更多 Java 面试速通,关注公众号持续更新。

