使用樂觀鎖解決電商中商品超賣的問題

電商項目中下單是要減庫存的,但是當多個用戶同時請求時會產生併發,導致多個線程同時減庫存,庫存可能變爲負數,在這裏我記一下一個簡單的防止超賣的方法。

 

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庫存數量代替了樂觀鎖的版本號,個人感覺相比較排它鎖的性能慢,和隊列的麻煩,這個方法最簡單,當然,要是項目併發很高的話還是推薦用列隊比較好。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章