引言
多個(gè)進(jìn)程或線程同時(shí)(或著說(shuō)在同一段時(shí)間內(nèi))訪問(wèn)同一資源會(huì)產(chǎn)生并發(fā)問(wèn)題。
?
銀行兩操作員同時(shí)操作同一賬戶就是典型的例子。比如A、B操作員同時(shí)讀取一余額為1000元的賬戶,A操作員為該賬戶增加100元,B操作員同時(shí)為該賬戶減去 50元,A先提交,B后提交。 最后實(shí)際賬戶余額為1000-50=950元,但本該為1000+100-50=1050。這就是典型的并發(fā)問(wèn)題。
?
從事零售供應(yīng)鏈庫(kù)存業(yè)務(wù),對(duì)庫(kù)存數(shù)量操作增減十分頻繁,同樣存在類似上述銀行取款遇到的問(wèn)題,庫(kù)存數(shù)量操作有誤勢(shì)必給前臺(tái)銷售產(chǎn)生損失影響,因此需要關(guān)注對(duì)庫(kù)存數(shù)量并發(fā)操作下的一致性。
?
下面通過(guò)一個(gè)真實(shí)的案例分享在并發(fā)情況下如何保證庫(kù)存數(shù)量的準(zhǔn)確性。
問(wèn)題是什么-加鎖失效
看看下面這段流程和代碼,思考會(huì)有并發(fā)問(wèn)題嗎?
?
1.加鎖前,獲取箱子明細(xì)數(shù)據(jù),此處在鎖之外,存在并發(fā)臟讀問(wèn)題
?
2.加鎖后,并進(jìn)行箱子上架分批次回傳業(yè)務(wù)處理
?
3.加鎖后,更新箱子明細(xì)上架數(shù)量邏輯:已上架數(shù)量 = 加鎖前的明細(xì)數(shù)據(jù)(臟讀) + 報(bào)文回傳的明細(xì)數(shù)據(jù) 直接進(jìn)行行更新
原因是什么-加鎖的位置不正確
核心的問(wèn)題原因
1.業(yè)務(wù)分布式鎖失效:使用分布式鎖加鎖了,但是仍然使用加鎖前查詢的數(shù)據(jù),導(dǎo)致出現(xiàn)臟讀
2.Mysql鎖失效:數(shù)據(jù)庫(kù)更新時(shí),未上任何鎖,導(dǎo)致臟讀的數(shù)據(jù)直接覆蓋更新當(dāng)前行
?
有同學(xué)這時(shí)問(wèn)了,為啥防重碼也沒(méi)有生效呢?
防重碼主要是用作冪等邏輯的,同一個(gè)請(qǐng)求多次處理,結(jié)果仍然是相同的。
但是這是兩次不同的請(qǐng)求,防重碼是不同的,因此不能只依賴防重碼保證一致性。
?
解決方案有哪些
1、代碼層面:使用鎖(如互斥鎖、讀寫(xiě)鎖、分布式鎖等)來(lái)控制資源的訪問(wèn),數(shù)據(jù)獲取的全部操作都需要再獲取鎖后才進(jìn)行。
將獲取箱子明細(xì)的代碼移動(dòng)到加鎖之后,只有獲取到分布式鎖,才能執(zhí)行分批次上架查詢和更新(串行化)
對(duì)應(yīng)改造后的代碼:
?
2、數(shù)據(jù)庫(kù)層面:實(shí)現(xiàn)事務(wù)管理,確保數(shù)據(jù)的一致性;合理設(shè)置事務(wù)隔離級(jí)別,以防止臟讀、或者采用樂(lè)觀鎖或悲觀鎖來(lái)處理并發(fā)更新,合理設(shè)計(jì)查詢效率,減少鎖競(jìng)爭(zhēng)。
數(shù)據(jù)庫(kù)的并發(fā)上鎖處理和業(yè)務(wù)代碼的上鎖是互補(bǔ)的關(guān)系
因?yàn)闊o(wú)法保證后續(xù)業(yè)務(wù)的調(diào)整或其他業(yè)務(wù)代碼的調(diào)用能始終保持獲取數(shù)據(jù)的一致性,數(shù)據(jù)庫(kù)的并發(fā)上鎖處理更多是一種兜底保證機(jī)制。
?
樂(lè)觀鎖更新
?
悲觀鎖更新
?
擴(kuò)展方案
1.應(yīng)用程序設(shè)計(jì): 在應(yīng)用程序設(shè)計(jì)階段,盡量避免長(zhǎng)時(shí)間持有數(shù)據(jù)庫(kù)連接或事務(wù),減少并發(fā)操作的可能性,利用AI代碼評(píng)審或者人工提前找出可能出現(xiàn)并發(fā)問(wèn)題的地方;合理設(shè)置鎖的粒度,避免鎖失效。
?
1. 網(wǎng)絡(luò)負(fù)載層面:采用限流控制訪問(wèn)頻率;采用分布式數(shù)據(jù)庫(kù),進(jìn)行數(shù)據(jù)分片,降低單節(jié)點(diǎn)并發(fā)壓力;使用負(fù)載均衡,將網(wǎng)絡(luò)請(qǐng)求分發(fā)到不同的服務(wù)器,提高系統(tǒng)處理并發(fā)的能力,防止系統(tǒng)過(guò)載。
?
1.請(qǐng)求層面:前端點(diǎn)擊防重、系統(tǒng)冪等防重、盡可能降低同一請(qǐng)求的多次重試訪問(wèn)引起的一致性問(wèn)題。
?
通過(guò)以上措施,可以在不同層面有效地防止并發(fā)問(wèn)題,保證系統(tǒng)的數(shù)據(jù)的一致性
審核編輯 黃宇
-
分布式
+關(guān)注
關(guān)注
1文章
924瀏覽量
74610 -
代碼
+關(guān)注
關(guān)注
30文章
4825瀏覽量
69035
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
非阻塞賦值容易錯(cuò)語(yǔ)法點(diǎn)討論
Linux高級(jí)編程---互斥鎖
轉(zhuǎn)第16章 FreeRTOS調(diào)度鎖,任務(wù)鎖和中斷鎖
STM32F427的FMC地址數(shù)據(jù)總線復(fù)用控制SRAM必須要加鎖存器嗎
設(shè)計(jì)電子密碼鎖時(shí),怎么實(shí)現(xiàn)控制密碼輸錯(cuò)幾次就不能再輸入的功能
帶自鎖功能的密碼鎖制作方法分享
Altium Designer規(guī)則設(shè)計(jì)技巧之過(guò)孔和焊盤(pán)
![Altium Designer規(guī)則設(shè)計(jì)技巧<b class='flag-5'>之過(guò)</b>孔和焊盤(pán)](https://file.elecfans.com/web1/M00/55/7C/pIYBAFssbnWASITJAAAruyRqeiA263.jpg)
詳解非鎖/互鎖/自鎖的區(qū)別
指紋密碼鎖失效原因及對(duì)應(yīng)的解決方案
select......for update會(huì)鎖表還是鎖行?
Linux互斥鎖的作用 互斥鎖是什么
讀寫(xiě)鎖的實(shí)現(xiàn)原理規(guī)則
![讀寫(xiě)<b class='flag-5'>鎖</b>的實(shí)現(xiàn)原理規(guī)則](https://file1.elecfans.com/web2/M00/8D/61/wKgZomS5-WaANQaWAADcVJ1xAOk056.jpg)
數(shù)據(jù)庫(kù)如何實(shí)現(xiàn)分布式鎖
什么是分布式鎖 Redis的五種分布式鎖方案
![什么是分布式<b class='flag-5'>鎖</b> Redis的五種分布式<b class='flag-5'>鎖</b>方案](https://file1.elecfans.com/web2/M00/AB/8F/wKgZomU16pqARgaIAAAbQl1drak020.png)
評(píng)論