溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

分布式鎖的原理與實(shí)現(xiàn)是什么

發(fā)布時(shí)間:2021-10-13 09:53:12 來源:億速云 閱讀:124 作者:iii 欄目:編程語言

這篇文章主要講解了“分布式鎖的原理與實(shí)現(xiàn)是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“分布式鎖的原理與實(shí)現(xiàn)是什么”吧!

為什么會(huì)出現(xiàn)分布式鎖?

如下圖所示,一個(gè)應(yīng)用被部署到多個(gè)機(jī)器上做負(fù)載均衡。為了保證一個(gè)方法或?qū)傩栽诟卟l(fā)情況下的同一時(shí)間只能被同一個(gè)線程執(zhí)行,我們該如何解決這個(gè)問題呢?
分布式鎖的原理與實(shí)現(xiàn)是什么
在傳統(tǒng)單體應(yīng)用單機(jī)部署的情況下,可以使用并發(fā)處理相關(guān)的功能(如Java并發(fā)處理相關(guān)的API:ReentrantLcok或synchronized)進(jìn)行互斥控制來解決。但是,隨著業(yè)務(wù)的發(fā)展,系統(tǒng)架構(gòu)也會(huì)逐步優(yōu)化升級,原本單體單機(jī)部署的系統(tǒng)被演化成分布式集群系統(tǒng),由于分布式系統(tǒng)多線程、多進(jìn)程并且分布在多個(gè)不同機(jī)器上,這將使原單機(jī)部署情況下的并發(fā)控制鎖策略無法滿足,并不能提供分布式鎖的能力。為了解決這個(gè)問題就需要一種跨機(jī)器的互斥機(jī)制來控制共享資源的訪問,這就是分布式鎖解決的難題!

分布式鎖應(yīng)用場景有哪些?

針對分布式鎖的目的來反向推導(dǎo)其應(yīng)用場景,主要包括兩類:

1、處理效率提升:應(yīng)用分布式鎖,可以減少重復(fù)任務(wù)的執(zhí)行,避免資源處理效率的浪費(fèi);

2、數(shù)據(jù)準(zhǔn)確性保障:使用分布式鎖可以放在數(shù)據(jù)資源的并發(fā)訪問,避免數(shù)據(jù)不一致情況,甚至數(shù)據(jù)損失等。

分布式鎖的實(shí)現(xiàn)前提

分布式的CAP理論:

任何一個(gè)分布式系統(tǒng)都無法同時(shí)滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition tolerance),最多只能同時(shí)滿足兩項(xiàng)。

通常情況下,大家都會(huì)犧牲強(qiáng)一致性來換取系統(tǒng)的高可用性,這樣我們很多的場景,其實(shí)是只需為了保證數(shù)據(jù)的“最終一致性”。
需要注意的是,這個(gè)最終時(shí)間需要是用戶可以接受的范圍內(nèi)的。

另外,要實(shí)現(xiàn)分布式鎖,需要具備一些條件,主要包括以下幾項(xiàng):

1、在分布式系統(tǒng)環(huán)境下,一個(gè)方法在同一時(shí)間只能被一個(gè)機(jī)器的一個(gè)線程執(zhí)行;
2、獲取鎖與釋放鎖的高可用及高性能;
3、具備非阻塞鎖特性,獲取不到鎖將直接返回獲取鎖失?。?br/> 4、具備鎖失效機(jī)制,防止死鎖。

上述條件,主要突出鎖本身的提效和保障準(zhǔn)確性的應(yīng)用特性,同時(shí)避免其本身對資源訪問造成影響;

實(shí)現(xiàn)方式有哪些呢?

關(guān)于分布式鎖的實(shí)現(xiàn),可以分別控制在不同的環(huán)節(jié)。

分布式鎖的原理與實(shí)現(xiàn)是什么

常見的主要分為以下這幾種:

1、開源組件鎖控制:ZooKeeper

ZooKeeper 是一個(gè)分布式協(xié)調(diào)服務(wù)的開源框架。主要用來解決分布式集群中應(yīng)用系統(tǒng)的一致性的問題,例如怎樣避免同時(shí)操作同一數(shù)據(jù)造成臟讀的問題。ZooKeeper 本質(zhì)上是一個(gè)分布式的小文件存儲(chǔ)系統(tǒng)。提供基于類似于文件系統(tǒng)的目錄樹方式的數(shù)據(jù)存儲(chǔ),并且可以對樹種的節(jié)點(diǎn)進(jìn)行有效管理。
分布式鎖的原理與實(shí)現(xiàn)是什么
那如何使用ZooKeeper實(shí)現(xiàn)分布式鎖?

1)客戶端連接zookeeper,并在/tmp下創(chuàng)建臨時(shí)的且有序的子節(jié)點(diǎn),第一個(gè)客戶端對應(yīng)的子節(jié)點(diǎn)為lock-0000,第二個(gè)為lock-0001,以此類推;

2)客戶端獲取/lock下的子節(jié)點(diǎn)列表,判斷自己創(chuàng)建的子節(jié)點(diǎn)是否為當(dāng)前子節(jié)點(diǎn)列表中序號最小的子節(jié)點(diǎn),如果是則認(rèn)為獲得鎖,否則監(jiān)聽剛好在自己之前一位的子節(jié)點(diǎn)刪除消息,獲得子節(jié)點(diǎn)變更通知后重復(fù)此步驟直至獲得鎖;

例如/tmp下的子節(jié)點(diǎn)列表為:lock-0000、lock-0001、lock-0002,序號為1的客戶端監(jiān)聽序號為0的子節(jié)點(diǎn)刪除消息,序號為2的監(jiān)聽序號為1的子節(jié)點(diǎn)刪除消息。(業(yè)務(wù)代碼執(zhí)行完即刪除子節(jié)點(diǎn))

3)執(zhí)行業(yè)務(wù)代碼流程,刪除當(dāng)前客戶端對應(yīng)的子節(jié)點(diǎn),鎖釋放。

ZooKeeper分布式鎖方式,性能相對Redis方式較差,主要原因是寫操作(獲取鎖釋放鎖)都需要在Leader上執(zhí)行,然后同步到follower。

2、任務(wù)處理鎖控制:Redis

Redis 是完全開源免費(fèi)的,遵守BSD協(xié)議,是一個(gè)高性能的key-value數(shù)據(jù)庫。
主要的優(yōu)勢包括:

  • 性能極高 – Redis能讀的速度是11w+次/s,寫的速度是8w+次/s

  • 豐富的數(shù)據(jù)類型 – Redis主要支持 Strings, Lists, Hashes, Sets 及 Ordered Sets 數(shù)據(jù)類型

  • 原子性 – Redis的所有操作都是原子性的,同時(shí)Redis還支持對幾個(gè)操作合并后的原子性執(zhí)行

  • 豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。

Redis實(shí)現(xiàn)簡單分布式鎖過程:

(1)獲取鎖:使用setnx加鎖,并使用expire命令為鎖添加一個(gè)超時(shí)時(shí)間,超過該時(shí)間則自動(dòng)釋放鎖,鎖的value值為一個(gè)隨機(jī)生成的UUID,通過此在釋放鎖的時(shí)候進(jìn)行判斷。

(2)獲取鎖:設(shè)置一個(gè)獲取的超時(shí)時(shí)間,若超過這個(gè)時(shí)間則放棄獲取鎖。

(3)釋放鎖:通過UUID判斷是不是該鎖,若是該鎖,則執(zhí)行delete進(jìn)行鎖釋放。

分布式鎖的原理與實(shí)現(xiàn)是什么
利用Redis實(shí)現(xiàn)分布式鎖,實(shí)現(xiàn)可能存在的缺點(diǎn):

在執(zhí)行delete進(jìn)行釋放鎖的時(shí)候,假如操作刪除鎖動(dòng)作失敗,那此 Key-Value 過期時(shí)間則不好控制,可能會(huì)一直存在,可能對后續(xù)數(shù)據(jù)驗(yàn)證造成影響。

3、數(shù)據(jù)寫入鎖控制:MySQL

數(shù)據(jù)庫層面是最終數(shù)據(jù)寫入的時(shí)候,對數(shù)據(jù)做寫入控制處理,算是分布式鎖的最終末端環(huán)節(jié)。主要包括以下三種方式,下面分別介紹一下。

實(shí)現(xiàn)方式一:唯一索引

UNIQUE KEY `uidx_name` (`name`) USING BTREE;

上述case中,我們對 name 字段做了索引的唯一性約束,當(dāng)存在多個(gè)新增數(shù)據(jù)請求同時(shí)提交到數(shù)據(jù)庫的話,數(shù)據(jù)庫自身則會(huì)利用唯一索引,來保證數(shù)據(jù)的唯一性。

實(shí)現(xiàn)方式二:排他鎖

執(zhí)行以下SQL:

SELECT status FROM users WHERE id = 3 FOR UPDATE;

假如,在另一個(gè)事務(wù)中再次執(zhí)行:

SELECT status FROM users WHERE id = 3 FOR UPDATE;

則第二個(gè)事務(wù)會(huì)一直等待上一個(gè)事務(wù)的提交,此時(shí)第二個(gè)查詢處于阻塞的狀態(tài)。

排它鎖的應(yīng)用:

在進(jìn)行事務(wù)操作時(shí),通過 “FOR UPDATE” 語句,MySQL會(huì)對查詢結(jié)果集中每行數(shù)據(jù)都添加排他鎖,其他線程對該記錄的更新與刪除操作都會(huì)阻塞。排他鎖包含行鎖、表鎖。

實(shí)現(xiàn)方式三:樂觀鎖

實(shí)現(xiàn)邏輯:樂觀鎖每次在執(zhí)行數(shù)據(jù)修改操作時(shí),都會(huì)帶上一個(gè)數(shù)據(jù)版本號,一旦版本號和數(shù)據(jù)的版本號一致就可以執(zhí)行修改操作并對版本號執(zhí)行+1 操作,否則就執(zhí)行失敗。因?yàn)槊看尾僮鞯陌姹咎柖紩?huì)隨之增加,所以不會(huì)出現(xiàn) ABA 問題。

除了 version 以外,還可以使用時(shí)間戳,因?yàn)闀r(shí)間戳天然具有順序遞增性。

比較麻煩的一點(diǎn):就是在操作業(yè)務(wù)前,需要先查詢出當(dāng)前的 version 版本。

數(shù)據(jù)庫分布式鎖實(shí)現(xiàn)可能存在的缺點(diǎn):

  • DB操作性能較差,并且有鎖表的風(fēng)險(xiǎn);

  • 非阻塞操作失敗后,需要輪詢,占用cpu資源;

  • 長時(shí)間不commit或者長時(shí)間輪詢,可能會(huì)占用較多連接資源

感謝各位的閱讀,以上就是“分布式鎖的原理與實(shí)現(xiàn)是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對分布式鎖的原理與實(shí)現(xiàn)是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI