以下是针对「高并发库存抢购」问题的技术方案总结,结合常见场景和解决方案,按优先级排序讲解:
一、核心问题
高并发场景下,库存扣减易出现:
- 超卖:多个线程同时读取库存并扣减,导致库存为负。
- 锁竞争:悲观锁(如
synchronized)在高并发下性能低下。 - 热点数据:单个库存 key 成为性能瓶颈。
二、解决方案与技术选型
1. 错误做法:锁竞争(26.1)
- 问题:使用 JVM 级别锁(如
synchronized)或数据库行锁,高并发下线程阻塞严重。 - 后果:吞吐量骤降,甚至雪崩。
- 改进方向:避免全局锁,转向分布式锁或无锁方案。
2. 原子操作(26.2)
- 技术:Redis
DECR或INCRBY命令。 - 适用场景:单 key 库存,如
stock:prod_1。 - 问题:仅支持单个 key,无法应对多 key 场景(如库存拆分)。
- 优化:配合 Lua 脚本保证原子性(见 27.7)。
3. 令牌库存(26.3)
- 技术:预先生成 N 个令牌(如 Redis Set),每次扣减取走一个令牌。
- 适用场景:秒杀活动,库存量已知且固定。
- 问题:令牌耗尽后无法扩容,灵活性差。
4. 多库存秒杀(26.4)
- 技术:库存拆分 + 随机 key 选择。
- 实现:
java
复制
// 库存拆分为 10 个 key:stock:prod_1:0 ~ stock:prod_1:9
for (int i = 0; i < 10; i++) {
String key = "stock:prod_1:" + random.nextInt(10);
long stock = redis.decr(key); // 原子扣减
if (stock >= 0) return true; // 成功
}
- 优势:分散热点,减少锁竞争。
- 问题:最后少量库存需多次尝试,可结合 Lua 脚本优化(见 27.7)。
5. 自旋互斥超时锁(26.5)
- 技术:Redis 分布式锁(如
SETNX) + 自旋重试。 - 适用场景:需要强一致性的场景。
- 问题:锁过期风险(如 GC 导致锁提前释放),高并发下性能下降。
- 优化:使用 Redlock 算法或 Redisson 的高级锁。
6. CAS 乐观锁(26.6)
- 技术:基于版本号的 Compare-And-Swap(如 Redis
WATCH+MULTI)。 - 适用场景:冲突概率低的场景。
- 问题:高并发下冲突频繁,导致大量重试。
- 优化:结合 Lua 脚本减少网络往返(见 27.7)。
7. Redis Lua 方式实现 Redis 锁(26.7)
- 技术:Redis 内置 Lua 脚本,保证操作原子性。
- 示例:
lua
复制
local stock = redis.call("GET", KEYS[1]);
if tonumber(stock) > 0 then
redis.call("DECR", KEYS[1]);
return 1; // 成功
else
return 0; // 失败
end
![]()
引用
- 优势:避免网络延迟,原子性更强。
- 问题:Lua 脚本不支持事务嵌套,复杂场景需谨慎。
三、技术演进路线
- 基础阶段:原子操作(如
DECR)解决单 key 问题。 - 进阶阶段:Lua 脚本封装复杂逻辑,减少网络交互。
- 高阶阶段:库存拆分 + 分布式锁(如 Redisson)应对超高并发。
四、面试话术
在高并发库存抢购场景中,我们通常会采取分层解决方案:
避免锁竞争:优先使用原子操作(如 Redis
DECR)或 Lua 脚本,减少锁的使用。分散热点:通过库存拆分(如多 key 存储),将请求分散到不同 Redis 节点。
兜底方案:结合分布式锁(如 Redisson)处理极端场景,但需注意锁的超时和续期问题。
最终一致性:使用消息队列异步更新数据库,保证最终一致性。
关键原则是:用空间换时间——通过增加 key 数量分散压力,而非依赖单一锁
在高并发场景下,多个用户同时抢购同一商品库存,如果没有合理的并发控制机制,容易出现“超卖”(卖出比实际库存多的商品)或“少买”(库存未被充分利用)等问题。这是因为多个线程同时读取库存、扣减库存,中间缺乏原子性控制,导致数据不一致。
二、常见错误做法
- 先读再写:如先
get库存,再set扣减,中间没有加锁或原子控制,多个线程可能同时读到相同值,导致库存扣减错误。 - 数据库行锁:使用数据库行锁管理库存,虽然能保证一致性,但性能差,不适合高并发场景。
- 简单自旋锁:虽然能保证互斥,但大量线程循环抢锁会极大消耗 CPU 和 Redis 资源,导致系统性能下降。
三、推荐解决方案
1. 原子操作(如 Redis decr/incr)
使用 Redis 的原子指令(如 decr)直接扣减库存,通过返回值判断是否成功。例如:
bash
复制
redis> decr prod_stock
- 优点:轻量、高效,Redis 单线程模型天然保证原子性。

最低0.47元/天 解锁文章
816

被折叠的 条评论
为什么被折叠?



