1. 程式人生 > >如果你想搞懂“分散式鎖”,必須要看這篇文章 ,看了很意外!

如果你想搞懂“分散式鎖”,必須要看這篇文章 ,看了很意外!

對於鎖大家肯定不會陌生,在 Java 中 synchronized 關鍵字和 ReentrantLock 可重入鎖在我們的程式碼中是經常見的,一般我們用其在多執行緒環境中控制對資源的併發訪問。

但是隨著分散式的快速發展,本地的加鎖往往不能滿足我們的需要,在我們的分散式環境中上面加鎖的方法就會失去作用。


於是人們為了在分散式環境中也能實現本地鎖的效果,也是紛紛各出其招,今天讓我們來聊一聊一般分散式鎖實現的套路。




為何需要分散式鎖



Martin Kleppmann 是英國劍橋大學的分散式系統的研究員,之前和 Redis 之父 Antirez 進行過關於 RedLock(紅鎖,後續有講到)是否安全的激烈討論。


Martin 認為一般我們使用分散式鎖有兩個場景:

  • 效率:使用分散式鎖可以避免不同節點重複相同的工作,這些工作會浪費資源。比如使用者付了錢之後有可能不同節點會發出多封簡訊。

  • 正確性:加分散式鎖同樣可以避免破壞正確性的發生,如果兩個節點在同一條資料上面操作,比如多個節點機器對同一個訂單操作不同的流程有可能會導致該筆訂單最後狀態出現錯誤,造成損失。


分散式鎖的一些特點




當我們確定了在不同節點上需要分散式鎖,那麼我們需要了解分散式鎖到底應該有哪些特點?


分散式鎖的特點如下:

  • 互斥性:和我們本地鎖一樣互斥性是最基本,但是分散式鎖需要保證在不同節點的不同執行緒的互斥。

  • 可重入性:同一個節點上的同一個執行緒如果獲取了鎖之後那麼也可以再次獲取這個鎖。

  • 鎖超時:和本地鎖一樣支援鎖超時,防止死鎖。

  • 高效,高可用:加鎖和解鎖需要高效,同時也需要保證高可用防止分散式鎖失效,可以增加降級。

  • 支援阻塞和非阻塞:和 ReentrantLock 一樣支援 lock 和 trylock 以及 tryLock(long timeOut)。

  • 支援公平鎖和非公平鎖(可選):公平鎖的意思是按照請求加鎖的順序獲得鎖,非公平鎖就相反是無序的。這個一般來說實現的比較少。


常見的分散式鎖



我們瞭解了一些特點之後,我們一般實現分散式鎖有以下幾個方式:

  • MySQL

  • ZK

  • Redis

  • 自研分散式鎖:如谷歌的 Chubby。


下面分開介紹一下這些分散式鎖的實現原理。


 MySQL 

首先來說一下 MySQL 分散式鎖的實現原理,相對來說這個比較容易理解,畢竟資料庫和我們開發人員在平時的開發中息息相關。


對於分散式鎖我們可以建立一個鎖表:



前面我們所說的 lock(),trylock(long timeout),trylock() 這幾個方法可以用下面的虛擬碼實現。


lock()


lock 一般是阻塞式的獲取鎖,意思就是不獲取到鎖誓不罷休,那麼我們可以寫一個死迴圈來執行其操作:



mysqlLock.lcok 內部是一個 sql,為了達到可重入鎖的效果,我們應該先進行查詢,如果有值,需要比較 node_info 是否一致。


這裡的 node_info 可以用機器 IP 和執行緒名字來表示,如果一致就加可重入鎖 count 的值,如果不一致就返回 false。如果沒有值就直接插入一條資料。


虛擬碼如下:



需要注意的是這一段程式碼需要加事務,必須要保證這一系列操作的原子性。


tryLock() 和 tryLock(long timeout)


tryLock() 是非阻塞獲取鎖,如果獲取不到就會馬上返回,程式碼如下:



tryLock(long timeout) 實現如下:



mysqlLock.lock 和上面一樣,但是要注意的是 select … for update 這個是阻塞的獲取行鎖,如果同一個資源併發量較大還是有可能會退化成阻塞的獲取鎖。


unlock()


unlock 的話如果這裡的 count 為 1 那麼可以刪除,如果大於 1 那麼需要減去 1。



鎖超時


我們有可能會遇到我們的機器節點掛了,那麼這個鎖就不會得到釋放,我們可以啟動一個定時任務,通過計算一般我們處理任務的時間。


比如是 5ms,那麼我們可以稍微擴大一點,當這個鎖超過 20ms 沒有被釋放我們就可以認定是節點掛了然後將其直接釋放。


MySQL 小結:

  • 適用場景:MySQL 分散式鎖一般適用於資源不存在資料庫,如果資料庫存在比如訂單,可以直接對這條資料加行鎖,不需要我們上面多的繁瑣的步驟。

  • 比如一個訂單,我們可以用 select * from order_table where id = 'xxx' for update 進行加行鎖,那麼其他的事務就不能對其進行修改。

  • 優點:理解起來簡單,不需要維護額外的第三方中介軟體(比如 Redis,ZK)。

  • 缺點:雖然容易理解但是實現起來較為繁瑣,需要自己考慮鎖超時,加事務等等。效能侷限於資料庫,一般對比快取來說效能較低。對於高併發的場景並不是很適合。


樂觀鎖


前面我們介紹的都是悲觀鎖,這裡想額外提一下樂觀鎖,在我們實際專案中也是經常實現樂觀鎖,因為我們加行鎖的效能消耗比較大,通常我們對於一些競爭不是那麼激烈。

相關推薦

如果分散式必須文章 意外

對於鎖大家肯定不會陌生,在 Java 中 synchronized 關鍵字和 ReentrantLock 可重入鎖在我們的程式碼中是經常見的,一般我們用其在多執行緒環境中控制對資源的併發訪問。 但是隨著分散式的快速發展,本地的加鎖往往不能滿足我們的需要,在我們的分散式環境中上面加鎖的方法

Java分散式,分散式實現文章就對

隨著微處理機技術的發展,人們只需花幾百美元就能買到一個CPU晶片,這個晶片每秒鐘執行的指令比80年代最大的大型機的處理機每秒鐘所執行的指令還多。如果你願意付出兩倍的價錢,將得到同樣的CPU,但它卻以更高的時鐘速率執行。因此,最節約成本的辦法通常是在一個系統中使用集中在一起的大量的廉價CPU。所以,傾向

Java分布式實現文章就對

無法 同一時間 業務邏輯 spa 提升 常用 修改 步驟 val 前言: 隨著微處理機技術的發展,人們只需花幾百美元就能買到一個CPU芯片,這個芯片每秒鐘執行的指令比80年代最大的大型機的處理機每秒鐘所執行的指令還多。如果你願意付出兩倍的價錢,將得到同樣的CPU,

大資料就文章就夠

網際網路時代的到來,各種專業詞彙術語充斥著我們的大腦,大資料,人工智慧更是當下時代的熱點潮流,很多傳統企業都徘徊穿梭於這個潮流當中,傳統廣告的褪去,移動網際網路時代的大資料精準整合營銷變得越來越重要!   很多初學者,對大資料的概念都是模糊不清的,大資料是什麼,能做什麼,學的時候,該按照什麼線

那個小白說他還沒類和物件我一怒之下把文章扔給

二哥,我就是上次說你《教妹學Spring》看不懂的那個小白,沒想到你還特意寫了一篇入門級的 Java 基礎知識,這次真的看懂了,感覺好棒。請原諒我上次的唐突,二哥能夠照顧我們這些小白的學習進度,真的是良心了。 以上是讀者 KEL 在上一篇基礎知識文章釋出後特意給我發來的資訊,說實話,看完後蠻感動的,良

推薦:解一個專案完整測試流程文章就OK

推薦:想了解一個專案完整測試流程,看這篇文章就OK了        寫在前面:本文來自真實企業測試人員的工作總結,用一個專案的進行流程為線索,記錄每個階段測試包含的內容及關注點。 <ignore_js_op>   專案的測試流程大

CSS中如果實現元素浮動和清除浮動文章就足夠

浮動基本介紹 在標準文件流中元素分為2種,塊級元素和行內元素,如果想讓一些元素既要有塊級元素的特點也同時保留行內元素特點,只能讓這些元素脫離標準文件流即可。 浮動可以讓元素脫離標準文件流,可以實現讓多個元素排在同一行,並且可以設定寬高度。 其實浮動是通過float屬性來實現的。 float屬性值說明表:

HCIE學習和考試如何規劃、安排文章就夠(雖然骨感)

學習和備考HCIE 乾頤堂hcieHCIE之路分享下 備考HCIE 心酸之路去年三月份一個人踏上魔都奮鬥之路,之前在武漢 一直做華三的產品。 武漢準備考HCIE 一直等到來上海 ,去QYT 報了名,琉兒給我辦理好了一切。本以為會按照很順利的節奏參加軍哥的課程,從NA 開始學習。可是,生活總是不如人願。 從四月

讓安卓app不再卡頓?文章就夠

實踐 分析 net 差異 項目 void 應該 倒數 文件存儲 歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐幹貨哦~ 本文由likunhuang發表於雲+社區專欄 實現背景 應用的使用流暢度,是衡量用戶體驗的重要標準之一。Android 由於機型配置和系統的不同,

設計自己的微服務?文章就對

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~ 本文通過使用Spring Boot,Spring Cloud和Docker構建的概念驗證應用程式的示例,為了解常見的微服務架構模式提供了一個起點。 該程式碼在Github上可用,並且可以在Doc

AI晶片的過去和未來文章就夠

  文章釋出於公號【數智物語】 (ID:decision_engine),關注公號不錯過每一篇乾貨。       轉自:矽谷密探   相信你一定還記得擊敗了李世石和柯潔的谷歌“阿爾

微信小程式完整開發文章就夠

微信使用的開發語言和檔案很「特殊」。 小程式所使用的程式檔案型別大致分為以下幾種: ①WXML(WeiXin Mark Language,微信標記語言) ②WXSS(WeiXin Style

關於第三方支付文章就夠

更多 ets 二維 new 效能 一段時間 .aspx 銀行業務 多行 萬字長文為您介紹第三方支付:起源、發展與趨勢 隨著移動支付的快速發展,第三方支付已經深度融入到生活中,如果生活在一二線城市,從吃飯、購物、看電影、菜市場買菜到搭公交地鐵,你能想到的消費場景,基本都可以用

不知道Java類檔案結構的同學文章就夠

  一、前言   程式碼編譯的結果從本地機器碼轉變為位元組碼,是儲存格式發展的一小步,卻是程式語言發展的一大步。經過多年的發展,目前的計算機仍然只能識別0和1,但是由於近10年內虛擬機器以及大量建立在虛擬機器之上的程式語言如雨後春筍般出現並蓬勃發展,將我們編寫的程式編譯成二進位制本地機器碼(Native Co

spring boot入門文章就夠

一、SpringBoot入門 1、基本介紹 簡化Spring應用開發的一個框架、整個Spring技術棧的一個大整合;

CSS如何設定列表樣式屬性文章就夠用

列表樣式屬性 在HTML中有2種列表、無序列表和有序列表,在工作中無序列表比較常用,無序列表就是ul標籤和li標籤組合成的稱之為無序列表,那什麼是有序列表呢?就是ol標籤和li標籤組合成的稱之為有序列表,列表的基礎知識就簡單說明下,本章內容主要說明的是如何給列表設定樣式,若有不懂列表是什麼的園友筆者建議去W

CSS中如何使用背景樣式屬性文章就夠用

css背景樣式屬性介紹 背景樣式就是自定義HTML標籤的背景顏色或背景影象。 背景屬性說明表 屬性名 屬性值 描述 background-color #f00、red、rgb(255,0,0) 設定背景顏色。 background-image url(背景圖片路徑) 設定背景影象。

如果學習Java那麼就來看文章

一、前言 我是從大二開始學習的Java,當時的目標是Java Web開發,當時並不想考研,所以當時的學習是以就業為主,現在我大三了,學習Java Web開發已經一年了,因為種種原因,決定要考研,所以不得不暫時終止了Java Web的學習,部落格也可能會停更很長一段時間,雖然

(轉)清華博士王垠的退學申請——研究生無論研究都該讀讀文章

我覺得再沒有從實際出發的目標,我的研究就會完全變成紙張了,就像我高中感覺到的一樣。所以後來我就自己設立了一個研究方向,我把自己稱為“研 究博士生”,我要去了解博士生都是怎麼樣生活的。我就想知道有多少學生有跟我類似的困境。我跟很多朋友談過,去了解他們的苦衷,研究生也有,本科的也有。我覺得我還應該瞭解更多的人,就

文章的阿裏技術面就可以過關

再處理 code topic ash 接口 這一 分布式消息 mage 例如 摘要: 在美國的大學課程中,101是所有課程中的第一門,是新生入學後的必修課程。阿裏巴巴中間件技術專家劉振東在上周的Apache RocketMQ開發者沙龍北京站的活動上,進行了主題為《Apach