整理常见的商品超卖的解决方案

在日常的购物中,针对普通商品是卖的越多越好,但是某些商品为了吸引用户购买而调整商品价格到让人看了不得不买的程度,由于是亏本促销卖,所以这种商品的数据都是有上限的,超过上限越多就亏损越多。下面整理几种常见的防治商品超卖的解决方案。

1、加锁排队

原理:通过加锁的方式让线程排队处理业务,这种方式实现简单,但是高高并发下效率不高。

2、update语句限制

原理:在扣减库存的时候,sql更新上将库存大于0作为一个条件更新数据然后返回的影响行数:

(1)如果影响行数> 0,表示扣减库存成功

(2)如果影响行数<0,表示扣减库存失败

通过这种方式可以很好的防止超卖问题的出现,但是本方案不适用于在高并发场景下的使用,因为数据库将成为瓶颈。

3、数据库乐观锁方式

原理:在商品表中增加一个字段version,每次在更新的时候带上version字段作为更新的条件,然后返回的影响行数:

(1)如果影响行数> 0,表示扣减库存成功

(2)如果影响行数<0,表示扣减库存失败

4、临时表的方式

原理:扣减库存的时候,都要线查询日志表(第一次的事日志表没有的时候让线程创建一条数据插入的到数据库),然后执行扣减库存的操作,在扣减库存的时候可能会出现超卖的问题,但是在更新日志表的版本的是判断当前的版本是否被其他的线程操作过,如果被其他线程操作过就提示扣减库存失败,本次操作无效并会滚数据库数据。这样可以防止超卖的问题。

5、redis提前存入库存方式

原理:使用定时任务(如xxl-job)在商品开售的之前将商品的库存信息存放到redis中(key是商品的id,value为商品的库存),用户下单的时候先在redis扣减(使用redis的decrby命令)库存,如果扣减后大于0,就允许用户下单,反之不可以让用户下单。这样也可以很好地防止超卖现象的问题发生。

总结:以上整理几种常见的防止库存超卖的解决方案,我们需要根据实际的业务场景选择合适的方案来解决。在高并发下建议采用redis提前存库存的方案,因为此方案的性能更好。针对业务并发量不高的场景建议使用锁方式、update语句限制方式、乐观锁锁来实现,因为实现起来简单、高效。

4