一用户下单购买商品的情况下,如果有多个人同时下单减除库存的情况下,如果遇到了减去库存的并发问题这个时候应该怎么处理呢?
传统的业务流程场景下处悝流程是这样的:
1,库存查询通过dao查询商品库存,返回库存数量
2逻辑判断库存是否充足,充足进行库存减扣
update stock set stock=stock-#{count} where gid=#{gid}但是在减去库存的时候往往会出现一些意想不到的错误出错后程序设计可能会有“重试”机制,但是在重试时可能会得到错误的数据,导致重复减扣或者库存為负数
重试导致错误的根本原因,是因为“扣减”操作是一个非幂等的操作不能够重复执行,改成设置操作则不会有这个问题如下:假如用户购买三件商品,通过数据库查询返回商品余量为5,然后通过逻辑计算减去三件商品余2然后在设置数量2到数据库持久化
1,库存查询通过dao查询商品库存,假如返回库存数量为5
2判断库存是否充足,充足进行逻辑库存减扣设置数据库(逻辑计算5-3=2,new_stock=2)
这样虽然避免了程序出错“重试”机制的减扣没有导致数据出现错误,但是如果用户发生了并发的购买动作(秒杀类业务特别容易出现)流程如下:
鼡户A和用户B并发购买商品,此时同时查询数据库库存数量为5
用户A购买了3个库存于是库存要设置为2
用户B购买了2个库存,于是库存要设置为3此时场景应该是五个商品刚好售卖完,储存应该为0但是这两个设置库存的接口并发执行,库存会先变成2再变成3,导致数据不一致(實际卖出了5件商品但库存只扣减了2,最后一次设置库存会覆盖和掩盖前一次并发操作)
其根本原因是设置操作发生的时候,没有检查實际库存与查询出来的库存有没有变化理论上:库存为5时,用户A的库存设置才能成功
库存为5时用户B的库存设置才能成功
库存变为2了,鼡户B的set stock=3应该失败掉
这样修改后用户A设置库存为2了,用户B再去设置库存通过条件stock=#{old_stock}判断条件已经不满足了更新失败,从而保证了数据的一致性
在业务复杂,数据量大并发量大的情况下,库存扣减容易引发数据的不一致常见的优化方案有两个:
- 调用“设置库存”接口,能够保证数据的幂等性
- 在实现“设置库存”接口时需要加上原有库存的比较,才允许设置成功能解决高并发下库存扣减的一致性问题