主要是去解决 高并发抽奖场景下的库存扣减问题,核心思路是:用Redis分布式锁替代数据库行锁,通过细粒度锁设计提升并发能力。
原先用数据库用数据库行锁扣库存(就是SQL里加SELECT ... FOR UPDATE
)据库扛不住:每秒1万请求直接打垮MySQL锁太粗:整个活动一个锁,99%的请求在排队。
优化
redis去预扣减库存
先用INCR原子操作扣减库存计数
超出库存判断,进行DECR恢复原始库存
优化锁的粒度
传统方案:锁整个活动(
lock_activity_1001
)→ 所有用户抢同一把锁优化后:每个库存编号单独加锁(
lock_activity_1001_1
、lock_activity_1001_2
)// 为当前扣减的库存编号加锁 String lockKey = "lock_activity_" + activityId + "_" + stockUsed; redisUtil.setNx(lockKey, "1", 过期时间);
异步同步数据库
扣减Redis成功后发MQ
消费者异步更新数据库库存
应对极端情况的解决方案
Redis扣减成功但MQ发送失败:
定时任务对比Redis和数据库库存,补发MQ
用户付款失败:
释放锁并回滚Redis库存(DECR)
库存不一致:
运营后台强制同步按钮(一键对齐Redis和DB)
评论