您好,登錄后才能下訂單哦!
zookeeper中怎么實現(xiàn)分布式排它鎖,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學(xué)習下,希望你能有所收獲。
一:分布式互斥鎖
分布式鎖主要用來在分布式系統(tǒng)中同步共享資源的訪問,在zookeeper中,并沒有像JAVA里一樣有Synchronized或者是ReentrantLock機制來實現(xiàn)鎖機制,但是在zookeeper中,實現(xiàn)起來更簡單:
我們可以講將zk的一個數(shù)據(jù)節(jié)點代表一個鎖,當多個客戶端同時調(diào)用create()節(jié)點創(chuàng)建節(jié)點的時候,zookeeper會保證只會有一個客戶端創(chuàng)建成功,那么我們就可以讓這個創(chuàng)建成功的客戶端讓其持有鎖,而其它的客戶端則注冊Watcher監(jiān)聽
當持有鎖的客戶端釋放鎖后,監(jiān)聽的客戶端就會收到Watcher通知,然后再去試圖獲取鎖,這樣反復(fù)即可。
二:大概流程
三 :代碼示例
import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; /** * 基于zookeeper實現(xiàn)互斥鎖 * * */ public class DistributedClient { private static final int SESSION_TIMEOUT = 5000; private String hosts = "192.168.8.88:2181,192.168.8.88:2182,192.168.8.88:2183"; private String groupNode = "locks"; private String subNode = "sub"; private ZooKeeper zk; // 當前client創(chuàng)建的子節(jié)點 private volatile String thisPath; // 當前client等待的子節(jié)點 private volatile String waitPath; private CountDownLatch latch = new CountDownLatch(1); /** * 連接zookeeper * * @param countDownLatch */ public void connectZookeeper(final CountDownLatch countDownLatch) throws Exception { zk = new ZooKeeper(hosts, SESSION_TIMEOUT, new Watcher() { @Override public void process(WatchedEvent event) { try { if (event.getState() == KeeperState.SyncConnected) { latch.countDown(); } // 發(fā)生了waitPath的刪除事件 /** * 假設(shè)某個client在獲得鎖之前掛掉了, 由于client創(chuàng)建的節(jié)點是ephemeral類型的, * 因此這個節(jié)點也會被刪除, 從而導(dǎo)致排在這個client之后的client提前獲得了鎖. * 此時會存在多個client同時訪問共享資源. 如何解決這個問題呢? 可以在接到刪除通知的時候, * 進行一次確認, 確認當前的thisPath是否真的是列表中最小的節(jié)點. */ if (event.getType() == EventType.NodeDeleted && event.getPath().equals(waitPath)) { // 確認thisPath是否真的是列表中的最小節(jié)點 List<String> childrenNodes = zk.getChildren("/" + groupNode, false); String thisNode = thisPath .substring(("/">
可能的運行結(jié)果如下:
當前線程:pool-1-thread-16獲得了鎖:/locks/sub0000000053 當前線程:pool-1-thread-16已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000053 當前線程:pool-1-thread-20-EventThread獲得了鎖:/locks/sub0000000054 當前線程:pool-1-thread-20-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000054 當前線程:pool-1-thread-5-EventThread獲得了鎖:/locks/sub0000000055 當前線程:pool-1-thread-5-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000055 當前線程:pool-1-thread-2-EventThread獲得了鎖:/locks/sub0000000056 當前線程:pool-1-thread-2-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000056 當前線程:pool-1-thread-6-EventThread獲得了鎖:/locks/sub0000000057 當前線程:pool-1-thread-6-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000057 當前線程:pool-1-thread-10-EventThread獲得了鎖:/locks/sub0000000058 當前線程:pool-1-thread-10-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000058 當前線程:pool-1-thread-3-EventThread獲得了鎖:/locks/sub0000000059 當前線程:pool-1-thread-3-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000059 當前線程:pool-1-thread-11-EventThread獲得了鎖:/locks/sub0000000060 當前線程:pool-1-thread-11-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000060 當前線程:pool-1-thread-7-EventThread獲得了鎖:/locks/sub0000000061 當前線程:pool-1-thread-7-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000061 當前線程:pool-1-thread-13-EventThread獲得了鎖:/locks/sub0000000062 當前線程:pool-1-thread-13-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000062 當前線程:pool-1-thread-15-EventThread獲得了鎖:/locks/sub0000000063 當前線程:pool-1-thread-15-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000063 當前線程:pool-1-thread-1-EventThread獲得了鎖:/locks/sub0000000064 當前線程:pool-1-thread-1-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000064 當前線程:pool-1-thread-18-EventThread獲得了鎖:/locks/sub0000000065 當前線程:pool-1-thread-18-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000065 當前線程:pool-1-thread-4-EventThread獲得了鎖:/locks/sub0000000066 當前線程:pool-1-thread-4-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000066 當前線程:pool-1-thread-19-EventThread獲得了鎖:/locks/sub0000000067 當前線程:pool-1-thread-19-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000067 當前線程:pool-1-thread-14-EventThread獲得了鎖:/locks/sub0000000068 當前線程:pool-1-thread-14-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000068 當前線程:pool-1-thread-9-EventThread獲得了鎖:/locks/sub0000000069 當前線程:pool-1-thread-9-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000069 當前線程:pool-1-thread-8-EventThread獲得了鎖:/locks/sub0000000070 當前線程:pool-1-thread-8-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000070 當前線程:pool-1-thread-12-EventThread獲得了鎖:/locks/sub0000000071 當前線程:pool-1-thread-12-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000071 當前線程:pool-1-thread-17-EventThread獲得了鎖:/locks/sub0000000072 當前線程:pool-1-thread-17-EventThread已經(jīng)釋放了鎖,讓其它客戶端有機會去獲取,/locks/sub0000000072
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。