上一篇演示了基於Redis的Redisson分布式鎖實現,那今天我要再來說說基於Zookeeper的分布式現實。
Zookeeper分布式鎖實現
要用Zookeeper實現分布式鎖,我就不得不說說zookeeper的數據存儲。首先zookeeper的核心保存結構是一個DataTree數據結構,其實內部是一個Map<String, DataNode> nodes的數據結構,其中key是path,DataNode才是真正保存數據的核心數據結構,DataNode核心字段包括byte data[]用於保存節點內容。
一,Zookeeper的節點
節點是zookeeper(zk)中數據存儲的基礎結構,zk中萬物皆節點,就好比Java中萬物皆對象一樣。zk的數據模型就是基於節點的樹形結構,但zk規定每個節點的引用規則是路徑引用。每個節點中包含子節點引用、存儲數據、訪問權限以及節點元數據等四部分。

zookeeper中提供了節點類型主要有。
-
持久節點:節點創建后,就一直存在,直到有刪除操作來主動清除。
-
順序節點:假如當前有一個父節點為/lock,我們可以在這個父節點下面創建子節點;zk提供了一個可選的有序特性,例如我們可以創建子節點“/lock/test_”並且指明有序,那么zk在生成子節點時會根據當前子節點數量自動添加整數序號,如果第一個子節點為/lock/test_0000000000,下一個節點則為/lock/test_0000000001,依次類推。
-
臨時節點:客戶端可以建立一個臨時節點,在會話結束或者會話超時后,zookeeper會自動刪除該節點。
二,Zookeeper分布式鎖實現
Zookeeper實現分布式鎖的流程,假設鎖空間的根節點為/zklock:
1,客戶端連接zookeeper,並在/zklock下創建臨時的且有序的子節點。
第一個客戶端對應的子節點為:/zklock/test_lock_0000000000,第二個為:/zklock/test_lock_0000000001。以此類推。
2,客戶端獲取/zklock下的子節點列表,判斷自己創建的子節點是否為當前子節點列表中序號最小的子節點,如果是則認為獲得鎖,否則監聽/zklock的子節點變更消息,獲得子節點變更通知后重復此步驟直至獲得鎖;
3,執行業務代碼。
4,完成業務流程后,刪除對應的子節點並釋放鎖。

實現代碼

加鎖實現:

阻塞等待上一個鎖釋放

釋放鎖

測試:

啟動了5個線程來進行驗證,輸出結果如下。

注意:子節點的創建順序一定是從小到大的,但是控制台輸出結果中顯示創建順序是隨機的,是由於創建節點和輸出語句不是原子操作導致的。重點是鎖的獲取和釋放,從輸出結果中可以看出,每個線程只有在上一個節點被刪除后才能執行,一個基於zk的簡單的分布式鎖就實現了。
三,Curator分布式鎖實現
Zookeeper已經紅火了這么多年,實際上基於zk的分布式鎖目前已經有現成的實現框架,Curator就是Netflix開源的一套ZooKeeper客戶端框架,它提供了zk場景的絕大部分實現,使用Curator就不必關心其內部算法,Curator提供了來實現分布式鎖,用方法獲取鎖,以及用方法釋放鎖,同其他鎖一樣,方法需要放在finakky代碼塊中,確保鎖能正確釋放
Curator提供了四種分布式鎖,分別是:

-
InterProcessMutex:分布式可重入排它鎖
-
InterProcessSemaphoreMutex:分布式排它鎖
-
InterProcessReadWriteLock:分布式讀寫鎖
-
InterProcessMultiLock:將多個鎖作為單個實體管理的容器
首先在pom里依賴引入

properties配置

配置中心

Curator的分布式鎖實現



Controller里寫測試接口。

分布式鎖實現總結
前面講了基於Redis的分布式鎖實現,為什么這篇文章又要說基於Zookeeper的分布式鎖現實呢?讓我們先看看Redis和Zookeeper實現分布式鎖的區別吧。
區別:
-
技術層面:Redis 是nosql數據,而Zookeeper是分布式協調工具,主要用於分布式解決方案;
-
防死鎖:Redis是通過對key設置有效期來解決死鎖,而Zookeeper使用會話有效期方式解決死鎖現象;
-
效率方面:Redis是NoSQL數據庫,在效率上相對來說Redis就要比Zookeeper好很多;
-
可靠性:Redis有效期不是很好控制,可能會產生有效期延遲,而Zookeeper的臨時節點有先天性可控的有效期,所以相對來說Zookeeper比Redis可靠性高;
對比總結:Zookeeper分布式鎖可靠性比redis強,但由於需要創建節點刪除節點,所有效率相比Redis要低。那我在實際項目中我們如何選用呢?原則上如果並發量不是特別大,追求可靠性,那么首選zookeeper。而redis實現的分布式鎖響應更快,對並發的支持性能更好,如果為了效率,首選redis實現。
掃碼關注公眾號,發送關鍵詞獲取相關資料:
- 發送“Springboot”領取電商項目實戰源碼;
- 發送“SpringCloud”領取cloud學習實戰資料;