请稍等 ...
×

采纳答案成功!

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

红包并发下面的临界问题

当库存还大于1的时候,假如剩余的金额为2元
// 那么在计算红包序列的时候是不会取最后剩余的所有金额的
//仍然是以数量大于1的情况下计算的,
// 比如有2个用户同时抢,分别计算得到0.8元和1.1元
//这时1.1元的用户获得红包,同时还剩余0.9元,并且库存是1
// 这个时候0.8元的用户也去抢,符合乐观锁的逻辑,也抢到0.8元,
// 然后库存剩余为0,但剩余金额为0.1元,之后由于库存为0了,
// 剩余金额就不能被抢走了

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

2回答

枫荇 2020-03-18 17:19:16


同学,你好,由于网路问题,没有提交成功,幸好截了图,将就一下吧。

https://img1.sycdn.imooc.com//szimg/5e71e75e09477ff604150478.jpg




0 回复 有任何疑惑可以回复我~
枫荇 2020-03-18 09:54:57

你好同学,同一时间抢红包,一定是只有一个同学能拿到库存:

update red_envelope_goods  

set remain_amount=remain_amount-CAST(? AS DECIMAL(30,6)),  

remain_quantity=remain_quantity-1  

where envelope_no=?  

and remain_quantity>0 

and remain_amount >= CAST(? AS DECIMAL(30,6))

同学,可以看一下上面的SQL中 `remain_quantity>0 `  ,只有剩余数量大于1的时候,这个语句才会执行。

也就是说,当剩余数量为1的时候,同时有2个用户抢红包时,在数据库层面不存在绝对并行,update语句会串行执行,那么就只有一个用户执行成功,失败的用户程序就会返回错误:

// - 如果更新失败,也就是返回0,表示无可用红包数量和金额,抢红包失败
if rows <= 0 || err != nil {
  return errors.New("没有足够的红包和金额了")
}


0 回复 有任何疑惑可以回复我~
  • 提问者 qq_梦缘_3 #1
    是我没有把问题描述清楚。当红包剩余个数为2,剩余金额为2元时,这个时候两个人同时抢,因为两个人读到的剩余个数都为2,所以都是随机一个金额出来,假设A随机出0.8元,B随机出0.9元,两个人都能更新数据库成功,最后红包商品的红包剩余个数为0,剩余金额为0.3元。我之前想的是锁住红包id,当有人在抢这个红包的时候,其他人来抢就需要等待。qq群里有同学提出预先生成好单个小红包放到redis里,利用redis的特性。也想多了解一下,在企业开发中,一般又是怎么处理
    回复 有任何疑惑可以回复我~ 2020-03-18 10:41:57
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信