赞
踩
前言:
我们经常遇到对数据进行的场景,比如库存扣减(设置库存)、订单信息更新(设置订单)等。以库存扣减为例我们的常用做法为:
1.查询当前仓库库存
select num from store where id=3
2.代码中判断当前库存是否大于需求库存如果大于需求库存则进行库存更新操作
if(num-需求库存>0)
待更新库存=num-需求库存
3.更新仓库库存
update store set num=${待更新库存} where id=3
假定当前仓库为5、需求库存为3 ,因符合条件则设置库存为2
上述有没有问题呢?
当然!假设同时有2个库存扣减请求并发执行,请求1需求库存为4、请求2需求库存为3,请求1获取仓库库存5符合库存更新条件,在请求1更新前请求2同样获取仓库库存5也符合库存更新条件,最后系统剩余库存要么更新为1要么更新为2,导致数据不一致(实际卖出了7个库存但是只扣除了4个或3个)
想解决这种问题我们可以考虑串行处理,但串行处理的性能是极低的尤其是互联网产品大并发及实时行要求高的情况下此方案简直就是竞争对手给你的建议!
方案1:CAS
CAS(Compare And Set)
前言中最后一步更新操作的代码替换为:
update store set num=num-${待更新库存} where id=3 and num=${原num}
或者我们使用版本比较的方式校验数据有没有更新过,如果没有更新过则进行更新代码如下:
update store set num=num-${待更新库存} where id=3 and version=${原数据行版本}
但是使用行版本需要注意,必须保证任何更新操作都会引起行版本好的更新才可以,比如sqlserver的时间戳字段。但mysql的时间戳字段无法保证
此方案将避免因并发照成的库存多扣问题。
方案2:PAS
PAS(Permission And Set)
前言中最后一步更新操作的代码替换为:
update store set num=num-${待更新库存} where id=3 and num-${需求库存}>0
这样在满足实际库存大于需求库存的情况下所有的更新都会成功,大大提高了业务的通过率
优势:业务通过率最高变相的提升了执行效率
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。