使用乐观锁解决电商中商品超卖的问题

电商项目中下单是要减库存的,但是当多个用户同时请求时会产生并发,导致多个线程同时减库存,库存可能变为负数,在这里我记一下一个简单的防止超卖的方法。

 

JAVA代码:
 

private ResultDTO 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库存数量代替了乐观锁的版本号,个人感觉相比较排它锁的性能慢,和队列的麻烦,这个方法最简单,当然,要是项目并发很高的话还是推荐用列队比较好。

 

你可能感兴趣的:(web开发,JAVA,java,商品超卖,电商项目)