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

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

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

加鎖失效,非鎖之過,加之錯(cuò)也

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-11-05 17:52 ? 次閱讀

引言

多個(gè)進(jìn)程或線程同時(shí)(或著說在同一段時(shí)間內(nèi))訪問同一資源會(huì)產(chǎn)生并發(fā)問題。

?

銀行兩操作員同時(shí)操作同一賬戶就是典型的例子。比如A、B操作員同時(shí)讀取一余額為1000元的賬戶,A操作員為該賬戶增加100元,B操作員同時(shí)為該賬戶減去 50元,A先提交,B后提交。 最后實(shí)際賬戶余額為1000-50=950元,但本該為1000+100-50=1050。這就是典型的并發(fā)問題。

?

從事零售供應(yīng)鏈庫存業(yè)務(wù),對庫存數(shù)量操作增減十分頻繁,同樣存在類似上述銀行取款遇到的問題,庫存數(shù)量操作有誤勢必給前臺銷售產(chǎn)生損失影響,因此需要關(guān)注對庫存數(shù)量并發(fā)操作下的一致性。

?

下面通過一個(gè)真實(shí)的案例分享在并發(fā)情況下如何保證庫存數(shù)量的準(zhǔn)確性。

問題是什么-加鎖失效

看看下面這段流程和代碼,思考會(huì)有并發(fā)問題嗎?

wKgaomcoYW-Ae9-CAAFgOMxxRWA504.png

?

1.加鎖前,獲取箱子明細(xì)數(shù)據(jù),此處在鎖之外,存在并發(fā)臟讀問題

wKgZomcoYXCADd8pAAHpaEKHmfo247.png

?

2.加鎖后,并進(jìn)行箱子上架分批次回傳業(yè)務(wù)處理

wKgaomcoYXKAWp4kAAMnCp_ccqE913.png

?

3.加鎖后,更新箱子明細(xì)上架數(shù)量邏輯:已上架數(shù)量 = 加鎖前的明細(xì)數(shù)據(jù)(臟讀) + 報(bào)文回傳的明細(xì)數(shù)據(jù) 直接進(jìn)行行更新

wKgZomcoYXSAKeLHAAc6EXS9O2o758.png

原因是什么-加鎖的位置不正確

wKgaomcoYXWATQwzAAM5pLTPczs062.png

核心的問題原因

1.業(yè)務(wù)分布式鎖失效:使用分布式鎖加鎖了,但是仍然使用加鎖前查詢的數(shù)據(jù),導(dǎo)致出現(xiàn)臟讀

2.Mysql鎖失效:數(shù)據(jù)庫更新時(shí),未上任何鎖,導(dǎo)致臟讀的數(shù)據(jù)直接覆蓋更新當(dāng)前行

?

有同學(xué)這時(shí)問了,為啥防重碼也沒有生效呢?

防重碼主要是用作冪等邏輯的,同一個(gè)請求多次處理,結(jié)果仍然是相同的。

但是這是兩次不同的請求,防重碼是不同的,因此不能只依賴防重碼保證一致性。

?

解決方案有哪些

1、代碼層面:使用鎖(如互斥鎖、讀寫鎖、分布式鎖等)來控制資源的訪問,數(shù)據(jù)獲取的全部操作都需要再獲取鎖后才進(jìn)行。

將獲取箱子明細(xì)的代碼移動(dòng)到加鎖之后,只有獲取到分布式鎖,才能執(zhí)行分批次上架查詢和更新(串行化)

wKgZomcoYXaARau2AALOgDkTuUY983.png

對應(yīng)改造后的代碼:

wKgaomcoYXiAY4NNAAWUowUe7HI787.png

?

2、數(shù)據(jù)庫層面:實(shí)現(xiàn)事務(wù)管理,確保數(shù)據(jù)的一致性;合理設(shè)置事務(wù)隔離級別,以防止臟讀、或者采用樂觀鎖或悲觀鎖來處理并發(fā)更新,合理設(shè)計(jì)查詢效率,減少鎖競爭。

數(shù)據(jù)庫的并發(fā)上鎖處理和業(yè)務(wù)代碼的上鎖是互補(bǔ)的關(guān)系

因?yàn)闊o法保證后續(xù)業(yè)務(wù)的調(diào)整或其他業(yè)務(wù)代碼的調(diào)用能始終保持獲取數(shù)據(jù)的一致性,數(shù)據(jù)庫的并發(fā)上鎖處理更多是一種兜底保證機(jī)制。

?

樂觀鎖更新

wKgZomcoYXqAR3Y4AAJBf6DRpQk551.png

?

悲觀鎖更新

wKgaomcoYXuAOJ7IAAHiDtjHNY4446.png

?

擴(kuò)展方案

1.應(yīng)用程序設(shè)計(jì): 在應(yīng)用程序設(shè)計(jì)階段,盡量避免長時(shí)間持有數(shù)據(jù)庫連接或事務(wù),減少并發(fā)操作的可能性,利用AI代碼評審或者人工提前找出可能出現(xiàn)并發(fā)問題的地方;合理設(shè)置鎖的粒度,避免鎖失效。

?

1. 網(wǎng)絡(luò)負(fù)載層面:采用限流控制訪問頻率;采用分布式數(shù)據(jù)庫,進(jìn)行數(shù)據(jù)分片,降低單節(jié)點(diǎn)并發(fā)壓力;使用負(fù)載均衡,將網(wǎng)絡(luò)請求分發(fā)到不同的服務(wù)器,提高系統(tǒng)處理并發(fā)的能力,防止系統(tǒng)過載。

?

1.請求層面:前端點(diǎn)擊防重、系統(tǒng)冪等防重、盡可能降低同一請求的多次重試訪問引起的一致性問題。

?

通過以上措施,可以在不同層面有效地防止并發(fā)問題,保證系統(tǒng)的數(shù)據(jù)的一致性

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 分布式
    +關(guān)注

    關(guān)注

    1

    文章

    861

    瀏覽量

    74443
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4726

    瀏覽量

    68248
收藏 人收藏

    評論

    相關(guān)推薦

    阻塞賦值容易錯(cuò)語法點(diǎn)討論

    本帖最后由 eehome 于 2013-1-5 10:05 編輯 阻塞賦值容易錯(cuò)語法點(diǎn)討論請教下大家!我發(fā)現(xiàn)光盤里的例程有一段是這樣子的:always @(dac_sta
    發(fā)表于 12-22 09:53

    Linux高級編程---互斥

    當(dāng)前互斥被解鎖。pthread_mutex_trylock()函數(shù)是一個(gè)阻塞型的上鎖函數(shù),如果互斥沒被鎖住,pthread_mutex_trylock()函數(shù)將把互斥
    發(fā)表于 01-13 10:07

    轉(zhuǎn)第16章 FreeRTOS調(diào)度,任務(wù)和中斷

    的任務(wù)函數(shù),但是使用FreeRTOS現(xiàn)有的功能有兩種實(shí)現(xiàn)方法:(1)通過給調(diào)度器加鎖實(shí)現(xiàn)利用FreeRTOS的調(diào)度功能給調(diào)度器加鎖的話,將關(guān)閉任務(wù)切換功能,從而高優(yōu)先級任務(wù)也就無法
    發(fā)表于 09-01 07:45

    STM32F427的FMC地址數(shù)據(jù)總線復(fù)用控制SRAM必須要加鎖存器嗎

    用STM32F427的FMC控制SRAM,由于端口不夠用,想用FMC的數(shù)據(jù)地址總線復(fù)用功能,請問,是不是要加鎖存器存地址,求電路
    發(fā)表于 09-18 11:35

    設(shè)計(jì)電子密碼時(shí),怎么實(shí)現(xiàn)控制密碼輸錯(cuò)幾次就不能再輸入的功能

    設(shè)計(jì)電子密碼時(shí),怎么實(shí)現(xiàn)控制密碼輸錯(cuò)幾次就不能再輸入的功能
    發(fā)表于 06-19 20:36

    帶自功能的密碼制作方法分享

    開鎖。先按AN7不能開鎖已如上述。本密碼的按鍵順序只能是AN2、AN5、AN7。當(dāng)按下任何一個(gè)密碼鍵時(shí),SCR1導(dǎo)通,使VT2飽和導(dǎo)通,各按鍵失效,電路鎖定為關(guān)斷狀態(tài)。這時(shí)必須斷
    發(fā)表于 05-20 06:43

    Altium Designer規(guī)則設(shè)計(jì)技巧之過孔和焊盤

    本文主要介紹了Altium Designer規(guī)則設(shè)計(jì)技巧之過孔和焊盤.
    發(fā)表于 06-22 08:00 ?34次下載
    Altium Designer規(guī)則設(shè)計(jì)技巧<b class='flag-5'>之過</b>孔和焊盤

    詳解/互鎖/自的區(qū)別

    為了滿足不同的應(yīng)用需要,解碼接收電路的輸出模式通常分為,互鎖,自,混合輸出。幾種模式通俗的說,鎖相當(dāng)于輕觸開關(guān),互鎖相當(dāng)于風(fēng)扇的檔位開關(guān),自鎖相當(dāng)于電燈開關(guān)。
    發(fā)表于 10-07 15:26 ?7654次閱讀

    指紋密碼失效原因及對應(yīng)的解決方案

    密碼指紋失效怎么辦?指紋密碼失效是什么原因造成的?在部分用戶使用指紋的時(shí)候,會(huì)有小概率發(fā)生指紋失效
    發(fā)表于 06-12 14:30 ?10.3w次閱讀

    select......for update會(huì)表還是行?

    驗(yàn)證 結(jié)合一下實(shí)例驗(yàn)證 結(jié)果 ? select查詢語句是不會(huì)加鎖的,但是select .......for update除了有查詢的作用外,還會(huì)加鎖呢,而且它是悲觀。 那么它加的是行
    的頭像 發(fā)表于 10-10 15:54 ?1473次閱讀

    Linux互斥的作用 互斥是什么

    1、互斥 互斥(mutex),在訪問共享資源之前對互斥進(jìn)行上鎖,在訪問完成后釋放互斥(解鎖);對互斥進(jìn)行上鎖之后,任何其它試圖再次
    的頭像 發(fā)表于 07-21 11:13 ?888次閱讀

    讀寫的實(shí)現(xiàn)原理規(guī)則

    讀寫 互斥或自旋要么是加鎖狀態(tài)、要么是不加鎖狀態(tài),而且一次只有一個(gè)線程可以對其加鎖。 讀寫
    的頭像 發(fā)表于 07-21 11:21 ?846次閱讀
    讀寫<b class='flag-5'>鎖</b>的實(shí)現(xiàn)原理規(guī)則

    數(shù)據(jù)庫如何實(shí)現(xiàn)分布式

    主要是用來避免死鎖,防止不必要的線程等待和資源浪費(fèi) 可重入性 一個(gè)線程在持有的情況下,可以再次請求加鎖 高性能,高可用 加鎖釋放的操作盡量使用更少的資源,提高性能。同時(shí)也要保證高可
    的頭像 發(fā)表于 10-08 16:12 ?4531次閱讀

    什么是分布式 Redis的五種分布式方案

    本地加鎖的方式在分布式的場景下不適用,所以本文我們來探討下如何引入分布式解決本地的問題。本篇所有代碼和業(yè)務(wù)基于我的開源項(xiàng)目 PassJava。
    發(fā)表于 10-23 11:35 ?1041次閱讀
    什么是分布式<b class='flag-5'>鎖</b> Redis的五種分布式<b class='flag-5'>鎖</b>方案

    C語言加鎖沒有鎖住是什么原因?

    C語言加鎖沒有鎖住是什么原因? C語言中的機(jī)制主要是通過線程庫提供的函數(shù)來實(shí)現(xiàn)的,主要用于多線程編程中的資源同步與互斥。加鎖的目的是確保同一時(shí)刻只有一個(gè)線程可以訪問某個(gè)共享資源,以防止數(shù)據(jù)競爭
    的頭像 發(fā)表于 11-22 17:41 ?587次閱讀