1. 程式人生 > 其它 >庫存扣減和鎖

庫存扣減和鎖

常見的實現方案:

  1. 程式碼同步, 例如使用 synchronized ,lock 等同步方法
  2. 不查詢,直接更新 update table set surplus = (surplus - buyQuantity) where id = xx and (surplus - buyQuantity) > 0
  3. 使用CAS,update table set surplus = aa where id = xx and version = y
  4. 使用資料庫鎖,select xx for update
  5. 使用分散式鎖(zookeeper,redis等)

1.程式碼同步, 使用 synchronized ,lock 等同步方法

publicsynchronizedvoidbuy(StringproductName,IntegerbuyQuantity){
//其他校驗...
//校驗剩餘數量
Productproduct=從資料庫查詢出記錄;
if(product.getSurplus<buyQuantity){
return"庫存不足";
}

//set新的剩餘數量
product.setSurplus(product.getSurplus()-quantity);
//更新資料庫
update(product);
//記錄日誌...
//其他業務...
}

先說下這個方案的前提配置:

  • 使用spring 宣告式事務管理
  • 事務傳播機制使用預設的(PROPAGATION_REQUIRED)
  • 專案分層為controller-service-dao 3層, 事務管理在service層

這個方案不可行,主要是因為以下幾點:

1).synchronized 作用範圍是單個jvm例項, 如果做了叢集,分散式等,就沒用了

2).synchronized是作用在物件例項上的,如果不是單例,則多個例項間不會同步(這個一般用spring管理bean,預設就是單例)

3).單個jvm時,synchronized也不能保證多個數據庫事務的隔離性. 這與程式碼中的事務傳播級別,資料庫的事務隔離級別,加鎖時機等相關.

2.不查詢,直接更新

publicsynchronizedvoidbuy(StringproductName,IntegerbuyQuantity){
//其他校驗...
int影響行數=updatetablesetsurplus=(surplus-buyQuantity)whereid=1and(surplus-buyQuantity)>0;
if(result<0){
return"庫存不足";
}
//記錄日誌...
//其他業務...
}

這樣確實可以實現,不過有一些其他問題:

  • 不具備通用性,例如add操作
  • 庫存操作一般要記錄操作前後的數量等,這樣沒法記錄
  • 其他...

3.使用CAS, update table set surplus = aa where id = xx and yy = y

publicvoidbuy(StringproductName,IntegerbuyQuantity){
//其他校驗...
Productproduct=getByDB(productName);
int影響行數=updatetablesetsurplus=(surplus-buyQuantity)whereid=1andsurplus=查詢的剩餘數量;
while(result==0){
product=getByDB(productName);
if(查詢的剩餘數量>buyQuantity){
影響行數=updatetablesetsurplus=(surplus-buyQuantity)whereid=1andsurplus=查詢的剩餘數量;
}else{
return"庫存不足";
}
}

//記錄日誌...
//其他業務...
}

4.使用資料庫鎖, select xx for update

publicvoidbuy(StringproductName,IntegerbuyQuantity){
//其他校驗...
Productproduct=select*fromtablewherename=productNameforupdate;
if(查詢的剩餘數量>buyQuantity){
影響行數=updatetablesetsurplus=(surplus-buyQuantity)wherename=productName;
}else{
return"庫存不足";
}

//記錄日誌...
//其他業務...
}

5.使用分散式鎖(zookeeper,redis等)

分散式鎖的實現方案有很多:基於redis,基於zookeeper,基於資料庫等等