常見分佈式鎖實現方式

閱讀文本大概需要3分鐘。

0x01、基於mysql實現分佈式鎖

  基於分佈式鎖的實現,首先肯定是想單獨分離出一臺mysql數據庫,所有服務要想操作文件(共享資源),那麼必須先在mysql數據庫中插入一個標誌,插入標誌的服務就持有了鎖,並對文件進行操作,操作完成後,主動刪除標誌進行鎖釋放,其與服務會一直查詢數據庫,看是否標誌有被佔用,直到沒有標誌佔用時自己才能寫入標誌獲取鎖。

  但是這樣有這麼一個問題,如果服務(jvm1)宕機或者卡頓了,會一直持有鎖未釋放,這樣就造成了死鎖,因此就需要有一個監視鎖進程時刻監視鎖的狀態,如果超過一定時間未釋放就要進行主動清理鎖標記,然後供其與服務繼續獲取鎖。

  如果監視鎖字段進程和jvm1同時掛掉,依舊不能解決死鎖問題,於是又增加一個監視鎖字段進程,這樣一個進程掛掉,還有另一個監視鎖字段進程可以對鎖進行管理。這樣又誕生一個新的問題,兩個監視進程必須進行同步,否則對於過期的情況管理存在不一致問題。

因此存在以下問題,並且方案變得很複雜:

  • 監視鎖字段進程對於鎖的監視時間週期過短,仍舊會造成多售(jvm1還沒處理完其持有的鎖就被主動銷燬,造成多個服務同時持有鎖進行操作)。

  • 監視鎖字段進程對於鎖的監視時間週期過長,會造成整個服務卡頓過長,吞吐低下。

  • 監視鎖字段進程間的同步問題。

  • 當一個jvm持有鎖的時候,其餘服務會一直訪問數據庫查看鎖,會造成其餘jvm的資源浪費。        

0x02、基於Redis實現分佈式鎖

  相比較於基於數據庫實現分佈式鎖的方案來說,基於緩存來實現在性能方面會表現的更好一點,Redis就是其中一種。由於Redis可以設置字段的有效期,因此可以實現自動釋放超期的鎖,不需要多個監視鎖字段進程進行鎖守護,可以依舊存在上述mysql實現中除了3以外1、2、4中的問題。  

           

0x03、基於Zookeeper實現分佈式鎖

  基於以上兩種實現方式,有了基於zookeeper實現分佈式鎖的方案。由於zookeeper有以下特點:

  • 維護了一個有層次的數據節點,類似文件系統。

  • 有以下數據節點:臨時節點、持久節點、臨時有序節點(分佈式鎖實現基於的數據節點)、持久有序節點。

  • zookeeper可以和client客戶端通過心跳的機制保持長連接,如果客戶端鏈接zookeeper創建了一個臨時節點,那麼這個客戶端與zookeeper斷開連接後會自動刪除。

  • zookeeper的節點上可以註冊上用戶事件(自定義),如果節點數據刪除等事件都可以觸發自定義事件。

  • zookeeper保持了統一視圖,各服務對於狀態信息獲取滿足一致性。

Zookeeper的每一個節點,都是一個天然的順序發號器。

  在每一個節點下面創建子節點時,只要選擇的創建類型是有序(EPHEMERAL_SEQUENTIAL 臨時有序或者PERSISTENT_SEQUENTIAL 永久有序)類型,那麼,新的子節點後面,會加上一個次序編號。這個次序編號,是上一個生成的次序編號加一

  比如,創建一個用於發號的節點“/test/lock”,然後以他爲父親節點,可以在這個父節點下面創建相同前綴的子節點,假定相同的前綴爲“/test/lock/seq-”,在創建子節點時,同時指明是有序類型。如果是第一個創建的子節點,那麼生成的子節點爲/test/lock/seq-0000000000,下一個節點則爲/test/lock/seq-0000000001,依次類推,等等。
          

往期精彩

01 漫談發版哪些事,好課程推薦

02 Linux的常用最危險的命令

03 互聯網支付系統整體架構詳解

04 優秀的Java程序員必須瞭解的GC哪些

05 IT大企業有哪些病,別被這些病毀了自己?

關注我每天進步一點點

你點的在看,我都當成了喜歡


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章