库存扣减并发安全
库存扣减是高并发场景下最容易出错的地方。数据库行锁、Redis Decr、Lua 脚本、事务消息,四种方案孰优孰劣?
一、库存扣减的核心挑战
- 1.1 超卖——库存变成负数
- 1.2 少卖——库存有剩余但无法下单
- 1.3 热点商品——大量请求竞争同一行数据
- 1.4 扣减与支付的时序
二、方案 1:数据库行锁
- 2.1
UPDATE stock SET num = num - ? WHERE id = ? AND num >= ? - 2.2 行锁的排队效果——天然串行化
- 2.3 热点商品性能——TPS 受限于行锁
- 2.4 优化——拆行为多行
三、方案 2:Redis Decr
- 3.1
DECR stock_key——原子操作 - 3.2 判断返回值 >= 0——不会超卖
- 3.3 问题——Redis 宕机,库存数据丢失
- 3.4 持久化方案——AOF + RDB
四、方案 3:Redis + Lua 原子脚本
- 4.1 Lua 脚本保证”判断 + 扣减”的原子性
- 4.2 完整的 Lua 脚本示例
- 4.3 与单纯 DECR 的对比
- 4.4 支持批量扣减
五、方案 4:RocketMQ 事务消息
- 5.1 先扣 Redis 库存 + 发 half 消息
- 5.2 本地事务创建订单
- 5.3 异步扣减数据库库存
- 5.4 回查机制保证一致性
六、方案对比总结
- 并发能力——Redis Lua > Redis Decr > RocketMQ > 行锁
- 一致性——行锁 > RocketMQ > Redis Lua > Redis Decr
- 综合推荐——Redis Lua + 数据库异步扣减
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!