MySQL借助DB實(shí)現(xiàn)分布式鎖思路示例代碼詳解
文章主要給大家介紹了關(guān)于MySQL借助DB實(shí)現(xiàn)分布式鎖思路的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)...
文章主要給大家介紹了關(guān)于MySQL借助DB實(shí)現(xiàn)分布式鎖思路的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
前言
無(wú)論是單機(jī)鎖還是分布式鎖,原理都是基于共享的數(shù)據(jù),判斷當(dāng)前操作的行為。對(duì)于單機(jī)則是共享RAM內(nèi)存,對(duì)于集群則可以借助Redis,ZK,DB等第三方組件來(lái)實(shí)現(xiàn)。Redis,ZK對(duì)分布式鎖提供了很好的支持,基本上開(kāi)箱即用,然而這些組件本身要高可用,系統(tǒng)也需要強(qiáng)依賴這些組件,額外增加了不少成本。DB對(duì)于系統(tǒng)來(lái)說(shuō)本身就默認(rèn)為高可用組件,針對(duì)一些低頻的業(yè)務(wù)使用DB實(shí)現(xiàn)分布式鎖也是一個(gè)不錯(cuò)的解決方案,比如控制多機(jī)器下定時(shí)任務(wù)的起調(diào),針對(duì)審批回調(diào)處理等,本文將給出DB實(shí)現(xiàn)分布式鎖的一些場(chǎng)景以及解決方案,希望對(duì)你啟發(fā)。
表設(shè)計(jì)
首先要明確DB在系統(tǒng)中仍然需要認(rèn)為是最脆弱的一環(huán),因此在設(shè)計(jì)時(shí)需要考慮壓力問(wèn)題,即能應(yīng)用實(shí)現(xiàn)的邏輯就不要放到DB上實(shí)現(xiàn),也就是盡量少使用DB提供的鎖能力,如果是高并發(fā)業(yè)務(wù)則要避免使用DB鎖,換成Redis等緩存鎖更加有效。如清單1所示,該表中唯一的約束為lock_name,timestamp,version三者組合主鍵,下文會(huì)利用這三者實(shí)現(xiàn)悲觀鎖,樂(lè)觀鎖等業(yè)務(wù)場(chǎng)景。
清單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 '生成時(shí)間',
PRIMARY KEY (`lock_name`,`resource`,`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
觀鎖實(shí)現(xiàn)
對(duì)于悲觀鎖業(yè)務(wù)中常見(jiàn)的操作有以下兩種:
針對(duì)A:
A場(chǎng)景當(dāng)一臺(tái)機(jī)器獲取到鎖后,其他機(jī)器處于排隊(duì)狀態(tài),鎖釋放后其他機(jī)器才能夠繼續(xù)下去,這種應(yīng)用層面解決是相當(dāng)麻煩,因此一般使用DB提供的行鎖能力,即select xxx from xxx for update。A場(chǎng)景一般都和業(yè)務(wù)強(qiáng)關(guān)聯(lián),比如庫(kù)存增減,使用業(yè)務(wù)對(duì)象作為行鎖即可。需要注意的是,該方案本質(zhì)上鎖壓力還是在數(shù)據(jù)庫(kù)上,當(dāng)阻塞住的線程過(guò)多,且操作耗時(shí),最后會(huì)出現(xiàn)大量鎖超時(shí)現(xiàn)象。
針對(duì)B:
針對(duì)B場(chǎng)景(tryLock)舉個(gè)具體業(yè)務(wù),在集群下每臺(tái)機(jī)器都有定時(shí)任務(wù),但是業(yè)務(wù)上要求同一時(shí)刻只能有一臺(tái)能正常調(diào)度。
解決思路是利用唯一主鍵約束,插入一條針對(duì)TaskA的記錄,版本則默認(rèn)為1,插入成功的算獲取到鎖,繼續(xù)執(zhí)行業(yè)務(wù)操作。這種方案當(dāng)機(jī)器掛掉就會(huì)出現(xiàn)死鎖,因此還需要有一個(gè)定時(shí)任務(wù),定時(shí)清理已經(jīng)過(guò)期的鎖,清理維度可以根據(jù)lock_name設(shè)置不同時(shí)間清理策略。
定時(shí)任務(wù)清理策略會(huì)額外帶來(lái)復(fù)雜度,假設(shè)機(jī)器A獲取到了鎖,但由于CPU資源緊張,導(dǎo)致處理變慢,此時(shí)鎖被定時(shí)任務(wù)釋放,因此機(jī)器B也會(huì)獲取到鎖,那么此時(shí)就出現(xiàn)同一時(shí)刻兩臺(tái)機(jī)器同時(shí)持有鎖的現(xiàn)象,解決思路:把超時(shí)時(shí)間設(shè)置為遠(yuǎn)大于業(yè)務(wù)處理時(shí)間,或者增加版本機(jī)制改成樂(lè)觀鎖。
insert into lock set lock_name='TaskA' , resource='鎖住的業(yè)務(wù)',version=1,gmt_create=now()
success: 獲取到鎖
failed:放棄操作
釋放鎖
樂(lè)觀鎖實(shí)現(xiàn)
針對(duì)樂(lè)觀鎖場(chǎng)景,舉個(gè)具體業(yè)務(wù),在后臺(tái)系統(tǒng)中經(jīng)常使用大json擴(kuò)展字段存儲(chǔ)業(yè)務(wù)屬性,在涉及部分更新時(shí),需要先查詢出來(lái),合并數(shù)據(jù),寫入到DB,這個(gè)過(guò)程中如果存在并發(fā),則很容易造成數(shù)據(jù)丟失,因此需要使用鎖來(lái)保證數(shù)據(jù)一致性,相應(yīng)操作如下所示,針對(duì)樂(lè)觀鎖,不存在死鎖,因此這里直接存放業(yè)務(wù)id字段,保證每一個(gè)業(yè)務(wù)id有一條對(duì)應(yīng)的記錄,并且不需要對(duì)應(yīng)的定時(shí)器清除
。
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ù),寫回?cái)?shù)據(jù)
寫回到DB: update lock set version=version+1 where lock_name='業(yè)務(wù)名稱' and resource='業(yè)務(wù)id' and version= #{version};
寫回成功: 操作成功
寫回失敗: 回滾事務(wù),從頭操作
分布式鎖的原理實(shí)際上很容易理解,難的是如何在具體業(yè)務(wù)場(chǎng)景上選擇最合適的方案。無(wú)論是哪一種鎖方案都是與業(yè)務(wù)密切關(guān)聯(lián),總之沒(méi)有完美的分布式鎖方案,只有最適合當(dāng)前業(yè)務(wù)的鎖方案。樂(lè)觀鎖寫入失敗會(huì)回滾整個(gè)事務(wù),因此如果寫入沖突很頻繁的場(chǎng)景不適合使用樂(lè)觀鎖,大量的事務(wù)回滾會(huì)給DB巨大壓力,最終影響到具體業(yè)務(wù)系統(tǒng)。
總結(jié)
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,
- MySQL多版本并發(fā)控制MVCC的實(shí)現(xiàn)示例代碼介紹
- mysql group_concat 實(shí)現(xiàn)把分組字段寫成一行的方法
- mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)多表關(guān)聯(lián)統(tǒng)計(jì)、子查詢統(tǒng)計(jì)示例
- MySQL InnoDB數(shù)據(jù)庫(kù)如何保證事務(wù)特性示例詳解
- 數(shù)據(jù)庫(kù) MySQL8.0+常用命令及操作命令詳解
- Mysql8.0.17數(shù)據(jù)庫(kù)安裝圖文教程
- SQL Server 2000/2005/2008刪除或壓縮數(shù)據(jù)庫(kù)日志的方
- SQL Server數(shù)據(jù)庫(kù)查看login所授予的具體權(quán)限問(wèn)題
- SQL Server數(shù)據(jù)庫(kù)怎么找出一個(gè)表包含的頁(yè)信息(Page)
- Windows server 2016服務(wù)器上安裝oracle數(shù)據(jù)庫(kù)的教程
MySQL多版本并發(fā)控制MVCC的實(shí)現(xiàn)示例代碼介紹
主要介紹了mysql多版本并發(fā)控制MVCC的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。事務(wù)隔...
mysql group_concat 實(shí)現(xiàn)把分組字段寫成一行的方法
文章主要介紹了mysql group_concat實(shí)現(xiàn)把分組字段寫成一行的方法,結(jié)合實(shí)例形式分析了group_concat函數(shù)的功能、查詢用法及相關(guān)操作技巧,需要的朋友可以參考下。本文實(shí)例講述...
mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)多表關(guān)聯(lián)統(tǒng)計(jì)、子查詢統(tǒng)計(jì)示例
文章主要介紹了mysql實(shí)現(xiàn)多表關(guān)聯(lián)統(tǒng)計(jì)(子查詢統(tǒng)計(jì)),結(jié)合具體案例形式分析了mysql多表關(guān)聯(lián)統(tǒng)計(jì)的原理、實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下。本文實(shí)例講述了my...
MySQL InnoDB數(shù)據(jù)庫(kù)如何保證事務(wù)特性示例詳解
文章主要給大家介紹了關(guān)于MySQL InnoDB如何保證事務(wù)特性的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起...
數(shù)據(jù)庫(kù) MySQL8.0+常用命令及操作命令詳解
文章主要介紹了MySQL8.0+常用命令及操作命令,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下。開(kāi)啟遠(yuǎn)程訪問(wèn)通過(guò)以下命令開(kāi)啟root用戶遠(yuǎn)程訪問(wèn)權(quán)限:CREATE USER 'root'...
Mysql8.0.17數(shù)據(jù)庫(kù)安裝圖文教程
本文通過(guò)圖文并茂的形式給大家介紹了Mysql8.0.17安裝,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下...
SQL Server 2000/2005/2008刪除或壓縮數(shù)據(jù)庫(kù)日志的方法
最近win2008 r2的服務(wù)器比較卡,打開(kāi)服務(wù)器顯示也特別慢,sqlserver業(yè)務(wù)費(fèi)正常執(zhí)行,服務(wù)器桌面操作也比較卡,經(jīng)過(guò)多方研究發(fā)現(xiàn)原來(lái)是sqlserver日志文件已經(jīng)達(dá)到了84G導(dǎo)致,這里就為大家分享一下解決方法,需要的朋友可以參考一下...
SQL Server數(shù)據(jù)庫(kù)查看login所授予的具體權(quán)限問(wèn)題
在SQL Server數(shù)據(jù)庫(kù)中如何查看一個(gè)登錄名(login)的具體權(quán)限呢,下面腳本之家小編給大家?guī)?lái)了SQL Server查看login所授予的具體權(quán)限問(wèn)題,感興趣的朋友一起看看吧...
SQL Server數(shù)據(jù)庫(kù)怎么找出一個(gè)表包含的頁(yè)信息(Page)
文章主要給大家介紹了關(guān)于SQL Server是如何找出一個(gè)表包含的頁(yè)信息(Page)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用SQL Server具有一定的參考學(xué)習(xí)價(jià)值,...
Windows server 2016服務(wù)器上安裝oracle數(shù)據(jù)庫(kù)的教程圖解
文章主要介紹了Windows server 2016 安裝oracle的教程圖解,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下 1.安裝oracle Oracle的安...