京东商品库存的扣除过程,如何防止超卖?

x33g5p2x  于2022-06-24 转载在 其他  
字(1.9k)|赞(0)|评价(0)|浏览(404)

在商品购买的过程中,库存的抵扣过程,一般操作如下:

1、select根据商品id查询商品的库存。

2、根据下单的数量,计算库存是否足够,如果存库不足则抛出库存不足的异常,如果库存足够,则减去扣除的库存得到最新的库存剩余值。

3、set设置最新的库存剩余值。

上述过程的伪代码如下:

  1. // 根据商品id获取商品剩余库存
  2. select stock_remaing from stock_table where id=${goodsId};
  3. // 操作库存
  4. // 比较库存
  5. if(stock_remaing <quantity){
  6.    // 抛出库存不足的异常
  7. }
  8. else{
  9.   // 抵扣以后的库存值
  10.   int new_stock=stock_remaing - quantity;
  11. }
  12. // 根据商品id设置计算后的库存
  13. update stock_table  set stock_remaing =${new_stock} id=${goodsId};

并发修改数据库存超卖

如果数据库事务的隔离级别不是串行化(serializable),根据事务的特性,在并发修改的时候,可能会出现写覆盖的问题。

假设,商品的剩余库存stock_remaing 为100,客户A下单20,客户B下单30,在并发扣库存的时候,可能存在超卖。如果客户A和客户B同时获取剩余库存为100,则会出现事务后提交的值会覆盖前一个客户提交的值,有可能剩余的库存是80或者70。

流程如下:

加锁更新存库

为了在事务控制中,防止写覆盖,你会想到使用select for update的方式,将该商品的库存锁住,然后执行余下的操作。

流程如下:

以上,使用悲观锁方式,在分布式服务中,如果并发情况比较高的时候,扣减库存的操作是串行操作,效率很低。

使用乐观锁的方式更新

在更新的时候,使用(CAS+版本号更新)+重试条件(重试次数或者重试时间限制)乐观锁的方式更新库存。此时,如果,客户A和客户B同时读取到库存剩余100,在更新的时候,有一个操作会失败。

流程如下:

该种方式可以大大提高并发性,也可以保证数据的一致性;通过重试次数和重试时间的条件控制,可以防止过多的重试带来的数据库压力。

可以使用直接递减的方式执行么?

在抵扣库存的时候,有的人提议不执行select,计算,set三段式的操作,直接扣减的方式,并且对于扣减到小于零的情况作了判断。伪代码如下:

  1. update stock_table set remaing_stock=remaing_stock-${quantity} 
  2. where id =商品id
  3. and remaing_stock>${quantity};

在分布式服务调用中,因为网络异常,获取服务器异常,可能在微服务调用时,存在服务重试。例如,场景的网关超时,服务重试机制。此时,该种方式不满足幂等性,而存在多扣的情况。例如,同一用户扣减库存时,服务重试,极端情况下,该用户扣减库存操作执行多次,则就出现了商品超卖。

可以使用redis进行库存的抵扣么?

由于没有研究过redis源码,对于这种方式参考了大牛的回复,答案是可以使用redis的事务性扣减余额,但在CAS机制上比mysql没有优势,高性能是因为其内存存储的原因,带来的副作用是数据有丢失风险。
原文:https://blog.csdn.net/new_com/article/details/105568124

  1. 推荐3个原创springboot+Vue项目,有完整视频讲解与文档和源码:
  2. dailyhub】【实战】带你从0搭建一个Springboot+elasticsearch+canal的完整项目视频讲解:https://www.bilibili.com/video/BV1Jq4y1w7Bc/
  3. 完整开发文档:https://www.zhuawaba.com/post/124
  4. 线上演示:https://www.zhuawaba.com/dailyhub
  5. VueAdmin】手把手教你开发SpringBoot+Jwt+Vue的前后端分离后台管理系统视频讲解:https://www.bilibili.com/video/BV1af4y1s7Wh/
  6. 完整开发文档前端:https://www.zhuawaba.com/post/18
  7. 完整开发文档后端:https://www.zhuawaba.com/post/19
  8. 线上演示:https://www.markerhub.com/vueadmin/
  9. VueBlog】基于SpringBoot+Vue开发的前后端分离博客项目完整教学视频讲解:https://www.bilibili.com/video/BV1PQ4y1P7hZ
  10. 完整开发文档:https://www.zhuawaba.com/post/17
  11. ---
  12. 关注我,学Java

相关文章