国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

庫存扣減和鎖常見的實現(xiàn)方案代碼

Android編程精選 ? 來源:CSDN博客 ? 作者:北京-小北 ? 2021-11-06 14:48 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

先說場景:

物品W現(xiàn)在庫存剩余1個, 用戶P1,P2同時購買.則只有1人能購買成功.(前提是不允許超賣)

秒殺也是類似的情況, 只有1件商品,N個用戶同時搶購,只有1人能搶到..

這里不談秒殺設(shè)計,不談使用隊列等使請求串行化,就談下怎么用鎖來保證數(shù)據(jù)正確.

常見的實現(xiàn)方案有以下幾種:

  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. 使用數(shù)據(jù)庫鎖, select xx for update
  5. 使用分布式鎖(zookeeper,redis等)

下面就針對這幾種方案來分析下;

1.代碼同步, 例如使用 synchronized ,lock 等同步方法

面試的時候,我經(jīng)常會問這個問題,很大一部分人都會回答用這個方案來實現(xiàn).

偽代碼如下:

publicsynchronizedvoidbuy(StringproductName,IntegerbuyQuantity){
//其他校驗...
//校驗剩余數(shù)量
Productproduct=從數(shù)據(jù)庫查詢出記錄;
if(product.getSurplusreturn"庫存不足";
}

//set新的剩余數(shù)量
product.setSurplus(product.getSurplus()-quantity);
//更新數(shù)據(jù)庫
update(product);
//記錄日志...
//其他業(yè)務(wù)...
}

在方法聲明加上synchronized關(guān)鍵字,實現(xiàn)同步,這樣2個用戶同時購買,到buy方法時候同步執(zhí)行,第2個用戶執(zhí)行的時候,會庫存不足.

嗯.. 看著挺合理的,以前我也是這么干的. 所以現(xiàn)在碰到別人這樣回答,我就會在心里默默的想.小伙子你是沒踩過這坑啊.

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

  • 使用spring 聲明式事務(wù)管理
  • 事務(wù)傳播機制使用默認的(PROPAGATION_REQUIRED)
  • 項目分層為controller-service-dao 3層, 事務(wù)管理在service層

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

1).synchronized 作用范圍是單個jvm實例, 如果做了集群,分布式等,就沒用了

2).synchronized是作用在對象實例上的,如果不是單例,則多個實例間不會同步(這個一般用spring管理bean,默認就是單例)

3).單個jvm時,synchronized也不能保證多個數(shù)據(jù)庫事務(wù)的隔離性. 這與代碼中的事務(wù)傳播級別,數(shù)據(jù)庫的事務(wù)隔離級別,加鎖時機等相關(guān).

3-1).先說隔離級別,常用的是 Read Committed 和 Repeatable Read ,另外2種不常用就不說了

3-1-1)RR(Repeatable Read)級別.mysql默認的是RR,事務(wù)開啟后,不會讀取到其他事務(wù)提交的數(shù)據(jù)

根據(jù)前面的前提,我們知道在buy方法時會開啟事務(wù).

假設(shè)現(xiàn)在有線程T1,T2同時執(zhí)行buy方法.假設(shè)T1先執(zhí)行,T2等待.

spring的事務(wù)開啟和提交等是通過aop(代理)實現(xiàn)的,所以執(zhí)行buy方法前,就會開啟事務(wù).

這時候T1,T2是兩個事務(wù),當(dāng)T1執(zhí)行完后,T2執(zhí)行,讀取不到T1提交的數(shù)據(jù),所以會出問題.

3-1-2).RC(Read Committed)級別.事務(wù)開啟后,可以讀取到其他事務(wù)提交的數(shù)據(jù)

看起來這個級別可以解決上面的問題.T2執(zhí)行時,可以讀取到T1提交的結(jié)果.

但是問題是,T2執(zhí)行的時候, T1的事務(wù)提交了嗎?

事務(wù)和鎖的流程如下

  1. 開啟事務(wù)(aop)
  2. 加鎖(進入synchronized方法)
  3. 釋放鎖(退出synchronized方法)
  4. 提交事務(wù)(aop)

可以看出是先釋放鎖,再提交事務(wù).所以T2執(zhí)行查詢,可能還是未讀到T1提交的數(shù)據(jù),還會出問題

3-2).根據(jù)3-1中的問題,發(fā)現(xiàn)主要矛盾是事務(wù)開啟和提交的時機與加鎖解鎖時機不一致.有小伙伴們可能就想到了解決方案.

3-2-1).在事務(wù)開啟前加鎖,事務(wù)提交后解鎖.

確實是可以,這相當(dāng)于事務(wù)串行化.拋開性能不談,來談?wù)勗趺磳崿F(xiàn).

如果使用默認的事務(wù)傳播機制,那么要保證事務(wù)開啟前加鎖,事務(wù)提交后解鎖,就需要把加鎖,解鎖放在controller層.

這樣就有個潛在問題,所有操作庫存的方法,都要加鎖,而且要是同一把鎖,寫起來挺累的.

而且這樣還是不能跨jvm.

3-2-2).將查詢庫存,扣減庫存這2步操作,單獨提取個方法,單獨使用事務(wù),并且事務(wù)隔離級別設(shè)置為RC.

這個其實和上面的3-2-1異曲同工,最終都是講加解鎖放在了事務(wù)開啟提交外層.

比較而言優(yōu)點是入口少了. controller不用處理.

缺點除了上面的不能跨jvm,還有就是 單獨的這個方法,需要放到另外的service類中.

因為使用spring,同一個bean的內(nèi)部方法調(diào)用,是不會被再次代理的,所以配置的單獨事務(wù)等需要放到另外的service bean 中

2.不查詢,直接更新

看完第一種方案,有小伙伴就說了. 你說的那么復(fù)雜,那么多問題,不就是因為查詢的數(shù)據(jù)不是最新的嗎?

我們不查詢,直接更新不就行啦.

偽代碼如下:

publicsynchronizedvoidbuy(StringproductName,IntegerbuyQuantity){
//其他校驗...
int影響行數(shù)=updatetablesetsurplus=(surplus-buyQuantity)whereid=1;
if(result0){
return"庫存不足";
}
//記錄日志...
//其他業(yè)務(wù)...
}

測試后發(fā)現(xiàn)庫存變成-1了, 繼續(xù)完善下

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

測試后,功能OK;

這樣確實可以實現(xiàn),不過有一些其他問題:

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

但是根據(jù)這個方案,可以引出方案3.

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

CAS是指compare/check and swap/set 意思都差不多,不必太糾結(jié)是哪個單詞

我們將上面的sql修改一下:

int影響行數(shù)=updatetablesetsurplus=newQuantitywhereid=1andsurplus=oldQuantity;

這樣,線程T1執(zhí)行完后,線程T2去更新,影響行數(shù)=0,則說明數(shù)據(jù)被更新, 重新查詢判斷執(zhí)行.偽代碼如下:

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

//記錄日志...
//其他業(yè)務(wù)...
}

看到重新查詢幾個字,小伙伴們應(yīng)該就又想到事務(wù)隔離級別問題了.

沒錯,所以上面代碼中的getByDB方法,必須單獨事務(wù)(注意同一個bean內(nèi)單獨事務(wù)不生效哦),而且數(shù)據(jù)庫的事務(wù)隔離級別必須是RC,

否則上面的代碼就會是死循環(huán)了.

上面的方案,可能會出現(xiàn)一個CAS中經(jīng)典問題. ABA的問題.

ABA是指:

  • 線程T1 查詢,庫存剩余 100
  • 線程T2 查詢,庫存剩余 100
  • 線程T1 執(zhí)行 sub update t set surplus = 90 where id = x and surplus = 100;
  • 線程T3 查詢, 庫存剩余 90
  • 線程T3 執(zhí)行add update t set surplus = 100 where id = x and surplus = 90;
  • 線程T2 執(zhí)行sub update t set surplus = 90 where id = x and surplus = 100;

這里線程T2執(zhí)行的時候,庫存的100已經(jīng)不是查詢到的100了,但是對于這個業(yè)務(wù)是不影響的.

一般的設(shè)計中CAS會使用version來控制.

updatetsetsurplus=90,version=version+1whereid=xandversion=oldVersion;

這樣,每次更新version在原基礎(chǔ)上+1,就可以了.

使用CAS要注意幾點,

  • 失敗重試次數(shù),是否需要限制
  • 失敗重試對用戶是透明的

4.使用數(shù)據(jù)庫鎖, select xx for update

方案3種的cas,是樂觀鎖的實現(xiàn), 而select for udpate 則是悲觀鎖. 在查詢數(shù)據(jù)的時候,就將數(shù)據(jù)鎖住.

偽代碼如下:

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

//記錄日志...
//其他業(yè)務(wù)...
}

線程T1 進行sub , 查詢庫存剩余 100

線程T2 進行sub , 這時候,線程T1事務(wù)還未提交,線程T2阻塞,直到線程T1事務(wù)提交或回滾才能查詢出結(jié)果.

所以線程T2查詢出的一定是最新的數(shù)據(jù).相當(dāng)于事務(wù)串行化了,就解決了數(shù)據(jù)一致性問題.

對于select for update,需要注意的有2點.

  1. 統(tǒng)一入口:所有庫存操作都需要統(tǒng)一使用 select for update ,這樣才會阻塞, 如果另外一個方法還是普通的select, 是不會被阻塞的

  2. 加鎖順序:如果有多個鎖,那么加鎖順序要一致,否則會出現(xiàn)死鎖.

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

使用分布式鎖,原理和方案1種的synchronized是一樣的.只不過synchronized的flag只有jvm進程內(nèi)可見,而分布式鎖的flag則是全局可見.方案4種的select for update 的flag 也是全局可見.

分布式鎖的實現(xiàn)方案有很多:基于redis,基于zookeeper,基于數(shù)據(jù)庫等等.

需要注意,使用分布式鎖和synchronized鎖有同樣的問題,就是鎖和事務(wù)的順序,這個在方案1里面已經(jīng)講過.不再重復(fù).

做個簡單總結(jié):

  • 方案1: synchronized等jvm內(nèi)部鎖不適合用來保證數(shù)據(jù)庫數(shù)據(jù)一致性,不能跨jvm
  • 方案2: 不具備通用性,不能記錄操作前后日志
  • 方案3: 推薦使用.但是如果數(shù)據(jù)競爭激烈,則自動重試次數(shù)會急劇上升,需要注意.
  • 方案4: 推薦使用.最簡單的方案,但是如果事務(wù)過大,會有性能問題.操作不當(dāng),會有死鎖問題
  • 方案5: 和方案1類似,只是能跨jvm
責(zé)任編輯:haq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7335

    瀏覽量

    94778
  • 源代碼
    +關(guān)注

    關(guān)注

    96

    文章

    2953

    瀏覽量

    70329

原文標(biāo)題:實踐角度,談?wù)剮齑婵蹨p和鎖

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    面試必看:排隊自旋之MCS實現(xiàn)原理與關(guān)鍵考點

    在并發(fā)編程面試中,“” 是繞不開的核心話題,而自旋作為輕量級的代表,其優(yōu)化方案更是高頻考點。
    的頭像 發(fā)表于 02-09 16:51 ?749次閱讀
    面試必看:排隊自旋<b class='flag-5'>鎖</b>之MCS<b class='flag-5'>鎖</b>的<b class='flag-5'>實現(xiàn)</b>原理與關(guān)鍵考點

    1688庫存API實戰(zhàn):巧設(shè)庫存預(yù)警閾值,實現(xiàn)智能提醒!

    導(dǎo)語:在電商運營中,庫存管理是至關(guān)重要的一環(huán)。庫存積壓會占用資金,庫存不足則可能導(dǎo)致訂單流失、客戶滿意度下降。1688平臺提供的庫存API,為我們
    的頭像 發(fā)表于 01-16 17:07 ?588次閱讀
    1688<b class='flag-5'>庫存</b>API實戰(zhàn):巧設(shè)<b class='flag-5'>庫存</b>預(yù)警閾值,<b class='flag-5'>實現(xiàn)</b>智能提醒!

    1688庫存API:多倉庫同步,庫存周轉(zhuǎn)快!

    ? 在電商和供應(yīng)鏈管理中,高效的庫存管理是企業(yè)成功的關(guān)鍵。1688平臺提供的庫存API,支持多倉庫同步功能,能顯著提升庫存周轉(zhuǎn)效率。本文將逐步介紹其技術(shù)實現(xiàn)和優(yōu)勢,幫助開發(fā)者理解如何利
    的頭像 發(fā)表于 01-08 14:47 ?251次閱讀
    1688<b class='flag-5'>庫存</b>API:多倉庫同步,<b class='flag-5'>庫存</b>周轉(zhuǎn)快!

    靠一套PDA手持終端+庫存預(yù)警系統(tǒng),一年幫公司省了540萬(實操拆解)

    失、盤虧浪費等行業(yè)痛點,為零售、制造、連鎖企業(yè)提供可復(fù)制的庫存降本方案,包含具體成本計算、實施步驟及常見問題解答。
    的頭像 發(fā)表于 12-30 12:14 ?273次閱讀
    靠一套PDA手持終端+<b class='flag-5'>庫存</b>預(yù)警系統(tǒng),一年幫公司省了540萬(實操拆解)

    電力調(diào)整器常見故障代碼

    電力調(diào)整器(又稱晶閘管調(diào)功器)的故障代碼因品牌和型號而異,沒有一個完全統(tǒng)一的標(biāo)準(zhǔn),但核心的保護功能是相似的。下表為你整理了合泉TM三相系列不同編碼系統(tǒng)中常見的故障代碼及其含義。
    的頭像 發(fā)表于 12-16 09:41 ?457次閱讀
    電力調(diào)整器<b class='flag-5'>常見</b>故障<b class='flag-5'>代碼</b>

    實時庫存同步接口技術(shù)詳解

    常見挑戰(zhàn)及解決方案,幫助開發(fā)者構(gòu)建高效可靠的接口。 1. 接口的核心概念 實時庫存同步接口基于事件驅(qū)動架構(gòu),通過API(如RESTful或GraphQL)實現(xiàn)數(shù)據(jù)交換。關(guān)鍵目標(biāo)是保證
    的頭像 發(fā)表于 10-10 14:33 ?516次閱讀
    實時<b class='flag-5'>庫存</b>同步接口技術(shù)詳解

    京東商品 SKU 信息接口技術(shù)干貨:數(shù)據(jù)拉取、規(guī)格解析與字段治理(附踩坑總結(jié) + 可運行代碼

    本文詳解京東商品SKU接口對接技術(shù),涵蓋核心參數(shù)、權(quán)限申請、簽名生成、規(guī)格解析及常見坑點解決方案,結(jié)合可運行代碼與實戰(zhàn)經(jīng)驗,助力開發(fā)者高效集成SKU數(shù)據(jù),實現(xiàn)
    的頭像 發(fā)表于 09-29 11:56 ?574次閱讀
    京東商品 SKU 信息接口技術(shù)干貨:數(shù)據(jù)拉取、規(guī)格解析與字段治理(附踩坑總結(jié) + 可運行<b class='flag-5'>代碼</b>

    唯品會:對接商品庫存API,實現(xiàn)限時特賣活動庫存動態(tài)預(yù)警,避免超賣

    。唯品會作為領(lǐng)先的特賣電商平臺,通過高效對接商品庫存API,實現(xiàn)庫存動態(tài)預(yù)警系統(tǒng),有效避免了超賣風(fēng)險。本文將逐步解析這一解決方案,幫助讀者理解其原理和實施過程。 一、超賣風(fēng)險的根源與
    的頭像 發(fā)表于 09-10 16:30 ?629次閱讀

    借助唯品會 API,唯品會店鋪運動商品庫存管理優(yōu)化

    的 API(應(yīng)用程序編程接口),幫助店鋪實現(xiàn)智能化庫存管理。本文將逐步介紹如何借助唯品會 API 優(yōu)化運動商品庫存,包括技術(shù)實現(xiàn)、核心算法和實際效益。 1.
    的頭像 發(fā)表于 09-03 17:11 ?822次閱讀
    借助唯品會 API,唯品會店鋪運動商品<b class='flag-5'>庫存</b>管理優(yōu)化

    ?一文了智能門鎖常見的幾種語音芯片方案

    智能是一種成熟且穩(wěn)定的產(chǎn)品類型,它對語音芯片的要求,大致集中于以下幾點: 使用簡單且好打樣:由于智能大多依托方案公司開發(fā),購買 pcba 回來組裝,產(chǎn)品類型豐富,語音需求多樣,頻繁打樣會影響開發(fā)
    的頭像 發(fā)表于 08-01 17:31 ?1148次閱讀

    淘寶API一鍵同步庫存,銷量翻倍輕松實現(xiàn)

    功能,您可以實時更新商品庫存,避免手動操作的繁瑣和錯誤,從而顯著提升銷售轉(zhuǎn)化率。許多成功店鋪的經(jīng)驗表明,合理利用此功能,銷量翻倍并非遙不可及的目標(biāo)。本文將一步步引導(dǎo)您如何實現(xiàn)這一過程,確保操作真實可靠。 什么是
    的頭像 發(fā)表于 07-28 14:48 ?541次閱讀
    淘寶API一鍵同步<b class='flag-5'>庫存</b>,銷量翻倍輕松<b class='flag-5'>實現(xiàn)</b>!

    API驅(qū)動的大型電商平臺庫存優(yōu)化

    實現(xiàn)系統(tǒng)間的無縫集成和數(shù)據(jù)實時交換,為庫存優(yōu)化提供了強大支持。本文將逐步探討API如何驅(qū)動庫存優(yōu)化,包括其原理、關(guān)鍵技術(shù)和實際應(yīng)用,幫助您理解并實施高效策略。 一、API在庫存管理中的
    的頭像 發(fā)表于 07-15 14:42 ?535次閱讀
    API驅(qū)動的大型電商平臺<b class='flag-5'>庫存</b>優(yōu)化

    蘇寧易購電商 API 接口,家電庫存管理智能方案

    的智能庫存管理方案,專為家電品類設(shè)計。本文將逐步解析這一方案的核心要素、實施路徑及實際效益,幫助企業(yè)高效優(yōu)化庫存運營。 一、電商庫存管理的痛
    的頭像 發(fā)表于 07-07 14:59 ?573次閱讀
    蘇寧易購電商 API 接口,家電<b class='flag-5'>庫存</b>管理智能<b class='flag-5'>方案</b>

    聯(lián)世界,智啟萬家,華普微藍牙智能解決方案

    密碼、指紋、刷卡與多模組合等主流門鎖形態(tài),支持與手機APP、小程序、智能中控網(wǎng)關(guān)等多終端互聯(lián),助力客戶快速實現(xiàn)智能門鎖產(chǎn)品的量產(chǎn)落地
    的頭像 發(fā)表于 06-26 15:46 ?820次閱讀
    <b class='flag-5'>鎖</b>聯(lián)世界,智啟萬家,華普微藍牙智能<b class='flag-5'>鎖</b>解決<b class='flag-5'>方案</b>

    RFID在服裝庫存中的應(yīng)用

    RFID是一種通過無線電波進行數(shù)據(jù)讀寫和物體識別的技術(shù)。它由電子標(biāo)簽、讀寫器和天線組成,能夠實現(xiàn)非接觸式的數(shù)據(jù)交互。相比傳統(tǒng)的條形碼技術(shù),RFID具有更高的效率、更強的抗污染能力和更遠的讀取距離
    的頭像 發(fā)表于 04-09 16:18 ?756次閱讀
    RFID在服裝<b class='flag-5'>庫存</b>中的應(yīng)用