请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

redis扣减库存是否需要添加分布式锁?

老师,
你好!请问redisTemplate.opsForValue().increment(key,amount*(-1))这个操作,如果有多线程(多用户)同时执行这个操作扣减库存,会不会有所不妥?
比如原有库存4,同时有两条线程甲和乙分别需要购买3个和2个库存。即便redis是单线程模型,可以将请求串行为先扣甲的3个,再扣乙的2个。
甲可以被顺利扣除,并且库存更新为4-3=1个,并且记录订单信息到消息队列。
乙执行了1-2=-1<0,扣减库存失败,并且无法下订单。
但此时由于库存已经被置为-1了,没法再接收后面的其他人新的下单了,只有当后面判断false的时候再加回去,后来者才可以重新下单。
是否需要引入类似cas/分布式锁的机制在increment(key,amount*(-1))这个操作前做一下检查?
比如扣减库存前先使用抢占redission的redlock,抢到了之后查询一下库存数量是否大于当前需要扣减的amount,要是是的话,再执行increment(key,amount*(-1))?

正在回答 回答被采纳积分+3

2回答

慕神3305675 2023-01-11 12:52:00

用lua就可以保证原子性了

0 回复 有任何疑惑可以回复我~
龙虾三少 2020-03-02 22:01:38

redis本身加减是原子操作

0 回复 有任何疑惑可以回复我~
  • 提问者 yidaimi #1
    老师,是的。我理解increment是一个原子操作。但是从本课程的代码中对于一个库存不足减扣的动作其实是做了一个先减后增的操作。并且这两个操作没有做成同一个原子操作。这就带来了问题:在减掉了之后并且在回增之前的这段时间内,其他用户都会下单失败。只有当回增操作执行之后后面的用户才能下单。这就会变成秒杀并不是先到先得的。要做到先到先得似乎只有靠分布式锁来将查询+扣库存做成一个原子操作才可以,但分布式锁也会影响系统吞吐量。请问老师生产环境上的代码是怎么做的?会用分布式锁保证先到先得的公平吗?还是不用锁,就像现在这个例子一样依赖increment的原子性?
    回复 有任何疑惑可以回复我~ 2020-03-02 22:22:01
  • 好问题啊,我也想知道,老师能不能简单介绍一下该怎么做。感谢了
    回复 有任何疑惑可以回复我~ 2020-07-07 19:54:34
  • 慕无忌9337457 回复 提问者 yidaimi #3
    如果你参加过真实的秒杀活动,基本都是没货了就售罄状态或者提示库存不足,采取预约方式预约资格和等待时间,到指定时间应用开放抢购(在这段时间加库存不给下单),抢购时间到了才是真正的先到先得,固定量的库存同一时间段让所有用户抢,这样比较公平。我感觉你的想法就是加一件就让用户抢一件,这样做的意义在哪里?
    回复 有任何疑惑可以回复我~ 2020-07-28 19:52:15
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信