加锁是为了解决高并发下的库存竞争问题,确保不会出现超卖情况。

整个是在校验完活动信息之后去,再实现库存扣减

整个setnx获取分布式锁的流程:

  • 获取抽奖活动库存的KEY

  • 使用Redis的incr命令原子性地扣减库存

  • 如果增加后的值超过总库存,则通过Redis的decr命令回滚并返回错误

  • 为当前库存占用生成一个唯一的细粒度的锁 Key

  • 使用setNx命令获取分布式锁并设置一个锁过期时间在活动结束时间

  • 如果成功,就删除锁,不超过就回滚

领取活动成功之后,再去发送MQ消息给生产者,消费者异步同步数据到数据库,同时通过定时任务扫描重发实现补偿机制。

为什么要在INCR之后还需要SETNX加锁,主要是防止重复处理,可能存在同一个用户多次发送请求,然后这个时候都通过了库存检查,然后多次请求抽奖,加了setnx保证同一个交易只会出现一次,实现了幂等防止了超卖。

第二次细化锁的粒度

第一层用 incr 操作库存Key,是单Key原子操作,时间复杂度O(1),能在超高并发下快速判断库存是否耗尽。

通过 incr 生成自增ID后动态加锁,按需分配,避免初始化成本,也防止锁Key无限膨胀。

第一层 incr 是‘预占库存’,第二层锁是‘确认独占’。如果后续流程失败(比如用户没支付),只需回滚 incr 的计数,而锁的粒度保证了回滚时不会干扰其他请求。

细粒度锁如果预先生成,需要维护大量Key,占用内存且难以管理。