解决商品超卖问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决商品超卖问题相关的知识,希望对你有一定的参考价值。
参考技术A 一般的商品预下单会有一下流程,判断商品的库存,如果有库存,那么减库存,生成订单(这两个操作是一个事务)。在高并发的情况下,会有超卖的情况下。问题产生的原因是:多个线程(请求)同时进入减库存的操作,判断商品库存的方法尽管有,但是判断通过了,解决方法有多个:
1.分布式情况下,采用分布式锁,可以用zookeeper+curator实现,在判断商品库存的方法前,先去申请锁
2.在更新库存的表中添加判断,and stock_count > 0(这里简化场景,秒杀业务一次只允许秒杀一个商品),如果一个用户只能秒杀一次商品,需要在关联表中,对用户id和商品id建立唯一索引。
使用乐观锁解决电商中商品超卖的问题
电商项目中下单是要减库存的,但是当多个用户同时请求时会产生并发,导致多个线程同时减库存,库存可能变为负数,在这里我记一下一个简单的防止超卖的方法。
JAVA代码:
private ResultDTO<Object> checkAndUpdateInventory(SampleInventoryDTO dto, int index) throws InterruptedException
if (index > 15)
throw new BusinessException("同时操作人数过多,请稍后再试!", DataContract.SAMPLE_INVENTORY_UPDATE_TOOMUCH_CODE);
if (index >= 3)
//如果三次以上都没有更新成功则睡眠100毫秒
Thread.sleep(100);
//根据商品ID查询库存
Integer inventory = productDao.queryInventory(dto.getProductNo());
ProductVO vo = new ProductVO ();
vo.setProductNo(dto.getProductNo());
vo.setQuantity(dto.getQuantity());
vo.setInventory(inventory);
if (inventory >= dto.getQuantity())
if (productDao.updateQuantityByVersion(vo) < 1)
return checkAndUpdateInventory(dto, ++index);
else
return ResponseUtil.generateSuccessDTO("修改库存成功.");
else
return ResponseUtil.generateFaileDTO("商品库存不足!", DataContract.SAMPLE_INVENTORY_NOT_ENOUGH_CODE);
再贴上关键的SQL代码(productDao.updateQuantityByVersion() 的SQL):
UPDATE SAMPLE
SET
INVENTORY= INVENTORY - #quantity
WHERE RECORD_NO=#sampleNo AND INVENTORY = #inventory AND INVENTORY >= #quantity
整体思路就是在更新库存之前先查询一下库存,判断是不是足够且有没有变动过,在执行更新SQL库存时如果库存不等于查出来的库存,则表示有其它线程修改了库存,因此进入递归重新查询库存,直到更新库存SQL执行成功,这里使用了quantity库存数量代替了乐观锁的版本号,个人感觉相比较排它锁的性能慢,和队列的麻烦,这个方法最简单,当然,要是项目并发很高的话还是推荐用列队比较好。
以上是关于解决商品超卖问题的主要内容,如果未能解决你的问题,请参考以下文章