红包并发下面的临界问题

来源:6-21 红包模块-抢红包应用服务层测试用例调试【调试方法和技巧】

qq_梦缘_3

2020-03-11

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

写回答

2回答

枫荇

2020-03-18


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

//img.mukewang.com/szimg/5e71e75e09477ff604150478.jpg




0
0

枫荇

2020-03-18

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

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
1
qq_梦缘_3
是我没有把问题描述清楚。当红包剩余个数为2,剩余金额为2元时,这个时候两个人同时抢,因为两个人读到的剩余个数都为2,所以都是随机一个金额出来,假设A随机出0.8元,B随机出0.9元,两个人都能更新数据库成功,最后红包商品的红包剩余个数为0,剩余金额为0.3元。我之前想的是锁住红包id,当有人在抢这个红包的时候,其他人来抢就需要等待。qq群里有同学提出预先生成好单个小红包放到redis里,利用redis的特性。也想多了解一下,在企业开发中,一般又是怎么处理
2020-03-18
共1条回复

仿微信抢红包 Golang实战多版本抢红包系统

Golang红包系统单体版+并发版+分布式+微服务版,四大金装版、超值必修课

582 学习 · 159 问题

查看课程