库存扣减是高并发场景下最容易出错的地方。数据库行锁、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 + 数据库异步扣减