怎么在MySQL中利用DB實現(xiàn)分布式鎖

怎么在MySQL中利用DB實現(xiàn)分布式鎖?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

創(chuàng)新互聯(lián)建站2013年至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項目網(wǎng)站設(shè)計、做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元阜陽做網(wǎng)站,已為上家服務(wù),為阜陽各地企業(yè)和個人服務(wù),聯(lián)系電話:13518219792

表設(shè)計

首先要明確DB在系統(tǒng)中仍然需要認為是最脆弱的一環(huán),因此在設(shè)計時需要考慮壓力問題,即能應(yīng)用實現(xiàn)的邏輯就不要放到DB上實現(xiàn),也就是盡量少使用DB提供的鎖能力,如果是高并發(fā)業(yè)務(wù)則要避免使用DB鎖,換成redis等緩存鎖更加有效。如清單1所示,該表中唯一的約束為lock_name,timestamp,version三者組合主鍵,下文會利用這三者實現(xiàn)悲觀鎖,樂觀鎖等業(yè)務(wù)場景。

清單1: 分布式鎖表結(jié)構(gòu)

CREATE TABLE `lock` (
`lock_name` varchar(32) NOT NULL DEFAULT '' COMMENT '鎖名稱',
`resource` bigint(20) NOT NULL COMMENT '業(yè)務(wù)主鍵',
`version` int(5) NOT NULL COMMENT '版本',
`gmt_create` datetime NOT NULL COMMENT '生成時間',
PRIMARY KEY (`lock_name`,`resource`,`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

悲觀鎖實現(xiàn)

對于悲觀鎖業(yè)務(wù)中常見的操作有以下兩種:

怎么在MySQL中利用DB實現(xiàn)分布式鎖

針對A:

A場景當一臺機器獲取到鎖后,其他機器處于排隊狀態(tài),鎖釋放后其他機器才能夠繼續(xù)下去,這種應(yīng)用層面解決是相當麻煩,因此一般使用DB提供的行鎖能力,即select xxx from xxx for update。A場景一般都和業(yè)務(wù)強關(guān)聯(lián),比如庫存增減,使用業(yè)務(wù)對象作為行鎖即可。需要注意的是,該方案本質(zhì)上鎖壓力還是在數(shù)據(jù)庫上,當阻塞住的線程過多,且操作耗時,最后會出現(xiàn)大量鎖超時現(xiàn)象。

針對B:

針對B場景(tryLock)舉個具體業(yè)務(wù),在集群下每臺機器都有定時任務(wù),但是業(yè)務(wù)上要求同一時刻只能有一臺能正常調(diào)度。
解決思路是利用唯一主鍵約束,插入一條針對TaskA的記錄,版本則默認為1,插入成功的算獲取到鎖,繼續(xù)執(zhí)行業(yè)務(wù)操作。這種方案當機器掛掉就會出現(xiàn)死鎖,因此還需要有一個定時任務(wù),定時清理已經(jīng)過期的鎖,清理維度可以根據(jù)lock_name設(shè)置不同時間清理策略。

定時任務(wù)清理策略會額外帶來復(fù)雜度,假設(shè)機器A獲取到了鎖,但由于CPU資源緊張,導(dǎo)致處理變慢,此時鎖被定時任務(wù)釋放,因此機器B也會獲取到鎖,那么此時就出現(xiàn)同一時刻兩臺機器同時持有鎖的現(xiàn)象,解決思路:把超時時間設(shè)置為遠大于業(yè)務(wù)處理時間,或者增加版本機制改成樂觀鎖。

insert into lock set lock_name='TaskA' , resource='鎖住的業(yè)務(wù)',version=1,gmt_create=now()
success: 獲取到鎖
failed:放棄操作
釋放鎖

樂觀鎖實現(xiàn)

針對樂觀鎖場景,舉個具體業(yè)務(wù),在后臺系統(tǒng)中經(jīng)常使用大json擴展字段存儲業(yè)務(wù)屬性,在涉及部分更新時,需要先查詢出來,合并數(shù)據(jù),寫入到DB,這個過程中如果存在并發(fā),則很容易造成數(shù)據(jù)丟失,因此需要使用鎖來保證數(shù)據(jù)一致性,相應(yīng)操作如下所示,針對樂觀鎖,不存在死鎖,因此這里直接存放業(yè)務(wù)id字段,保證每一個業(yè)務(wù)id有一條對應(yīng)的記錄,并且不需要對應(yīng)的定時器清除。

select * from lock where lock_name='業(yè)務(wù)名稱', resource='業(yè)務(wù)id';
不存在: insert into lock set lock_name='業(yè)務(wù)名稱', resource='業(yè)務(wù)id' , version=1;
獲取版本: version
業(yè)務(wù)操作: 取數(shù)據(jù),合并數(shù)據(jù),寫回數(shù)據(jù)
寫回到DB: update lock set version=version+1 where lock_name='業(yè)務(wù)名稱' and resource='業(yè)務(wù)id' and version= #{version};
寫回成功: 操作成功
寫回失敗: 回滾事務(wù),從頭操作

看完上述內(nèi)容,你們掌握怎么在MySQL中利用DB實現(xiàn)分布式鎖的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

分享標題:怎么在MySQL中利用DB實現(xiàn)分布式鎖
標題路徑:http://bm7419.com/article48/phodhp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊營銷型網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、商城網(wǎng)站企業(yè)建站、虛擬主機

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)