主要是去解决 高并发抽奖场景下的库存扣减问题,核心思路是:用Redis分布式锁替代数据库行锁,通过细粒度锁设计提升并发能力

原先用数据库用数据库行锁扣库存(就是SQL里加SELECT ... FOR UPDATE据库扛不住:每秒1万请求直接打垮MySQL锁太粗:整个活动一个锁,99%的请求在排队。

优化

  • redis去预扣减库存

    • 先用INCR原子操作扣减库存计数

    • 超出库存判断,进行DECR恢复原始库存

  • 优化锁的粒度

    • 传统方案:锁整个活动(lock_activity_1001)→ 所有用户抢同一把锁

    • 优化后:每个库存编号单独加锁(lock_activity_1001_1lock_activity_1001_2

      // 为当前扣减的库存编号加锁
      String lockKey = "lock_activity_" + activityId + "_" + stockUsed; 
      redisUtil.setNx(lockKey, "1", 过期时间);
  • 异步同步数据库

    • 扣减Redis成功后发MQ

    • 消费者异步更新数据库库存

应对极端情况的解决方案

  • Redis扣减成功但MQ发送失败:

定时任务对比Redis和数据库库存,补发MQ

  • 用户付款失败:

释放锁并回滚Redis库存(DECR

  • 库存不一致:

运营后台强制同步按钮(一键对齐Redis和DB)