成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

分布式協(xié)調(diào)框架Zookeeper核心設(shè)計(jì)理解與實(shí)戰(zhàn)

大數(shù)據(jù) 分布式
想起很久以前在某個(gè)客戶現(xiàn)場(chǎng),微服務(wù) B 突然無法調(diào)用到微服務(wù) A,為了使服務(wù)盡快正常恢復(fù),重啟了微服務(wù) B 。雖然故障原因找到了,但對(duì)于 Zookeeper 的理解還是不夠深刻,于是重新學(xué)習(xí)了 Zookeeper 的核心設(shè)計(jì),并記錄于此文共勉。

[[413943]]

本文轉(zhuǎn)載自微信公眾號(hào)「KK架構(gòu)」,作者wangkai 。轉(zhuǎn)載本文請(qǐng)聯(lián)系KK架構(gòu)公眾號(hào)。

一、前言

想起很久以前在某個(gè)客戶現(xiàn)場(chǎng),微服務(wù) B 突然無法調(diào)用到微服務(wù) A,為了使服務(wù)盡快正常恢復(fù),重啟了微服務(wù) B 。

但客戶不依不饒?jiān)儐栠@個(gè)問題出現(xiàn)的原因,于是我還大老遠(yuǎn)從杭州飛到深圳,現(xiàn)場(chǎng)排查問題。

最后的結(jié)論是,zk 在某時(shí)刻出現(xiàn)主備切換,此時(shí)微服務(wù) A(基于 dubbo)需要重新往 zk上注冊(cè),但是端口號(hào)變了。

但是微服務(wù) B 本地有微服務(wù) A rpc 接口的緩存,緩存里面還是舊的端口,所以調(diào)用不到。

解決方法就是,把微服務(wù)的 rpc 端口號(hào)改成固定的。

雖說原因找到了,但對(duì)于 Zookeeper 的理解還是不夠深刻,于是重新學(xué)習(xí)了 Zookeeper 的核心設(shè)計(jì),并記錄于此文共勉。

二、Zookeeper 核心架構(gòu)設(shè)計(jì)

1、Zookeeper 特點(diǎn)

(1)Zookeeper 是一個(gè)分布式協(xié)調(diào)服務(wù),是為了解決多個(gè)節(jié)點(diǎn)狀態(tài)不一致的問題,充當(dāng)中間機(jī)構(gòu)來調(diào)停。如果出現(xiàn)了不一致,則把這個(gè)不一致的情況寫入到 Zookeeper 中,Zookeeper 會(huì)返回響應(yīng),響應(yīng)成功,則表示幫你達(dá)成了一致。

比如,A、B、C 節(jié)點(diǎn)在集群?jiǎn)?dòng)時(shí),需要推舉出一個(gè)主節(jié)點(diǎn),這個(gè)時(shí)候,A、B、C 只要同時(shí)往 Zookeeper 上注冊(cè)臨時(shí)節(jié)點(diǎn),誰先注冊(cè)成功,誰就是主節(jié)點(diǎn)。

(2)Zookeeper 雖然是一個(gè)集群,但是數(shù)據(jù)并不是分散存儲(chǔ)在各個(gè)節(jié)點(diǎn)上的,而是每個(gè)節(jié)點(diǎn)都保存了集群所有的數(shù)據(jù)。

其中一個(gè)節(jié)點(diǎn)作為主節(jié)點(diǎn),提供分布式事務(wù)的寫服務(wù),其他節(jié)點(diǎn)和這個(gè)節(jié)點(diǎn)同步數(shù)據(jù),保持和主節(jié)點(diǎn)狀態(tài)一致。

(3)Zookeeper 所有節(jié)點(diǎn)的數(shù)據(jù)狀態(tài)通過 Zab 協(xié)議保持一致。當(dāng)集群中沒有 Leader 節(jié)點(diǎn)時(shí),內(nèi)部會(huì)執(zhí)行選舉,選舉結(jié)束,F(xiàn)ollower 和 Leader 執(zhí)行狀態(tài)同步;當(dāng)有 Leader 節(jié)點(diǎn)時(shí),Leader 通過 ZAB 協(xié)議主導(dǎo)分布式事務(wù)的執(zhí)行,并且所有的事務(wù)都是串行執(zhí)行的。

(4)Zookeeper 的節(jié)點(diǎn)個(gè)數(shù)是不能線性擴(kuò)展的,節(jié)點(diǎn)越多,同步數(shù)據(jù)的壓力越大,執(zhí)行分布式事務(wù)性能越差。推薦3、5、7 這樣的數(shù)目。

2、Zookeeper 角色的理解

Zookeeper 并沒有沿用 Master/Slave 概念,而是引入了 Leader,F(xiàn)ollower,Observer 三種角色。

通過 Leader 選舉算法來選定一臺(tái)服務(wù)器充當(dāng) Leader 節(jié)點(diǎn),Leader 服務(wù)器為客戶端提供讀、寫服務(wù)。

Follower 節(jié)點(diǎn)可以參加選舉,也可以接受客戶端的讀請(qǐng)求,但是接受到客戶端的寫請(qǐng)求時(shí),會(huì)轉(zhuǎn)發(fā)到 Leader 服務(wù)器去處理。

Observer 角色只能提供讀服務(wù),不能選舉和被選舉,所以它存在的意義是在不影響寫性能的前提下,提升集群的讀性能。

3、Zookeeper 同時(shí)滿足了 CAP 嗎?

答案是否,CAP 只能同時(shí)滿足其二。

Zookeeper 是有取舍的,它實(shí)現(xiàn)了 A 可用性、P 分區(qū)容錯(cuò)性、C 的寫入一致性,犧牲的是 C的讀一致性。

也就是說,Zookeeper 并不保證讀取的一定是最新的數(shù)據(jù)。如果一定要最新,需要使用 sync 回調(diào)處理。

三、核心機(jī)制一:ZNode 數(shù)據(jù)模型

Zookeeper 的 ZNode 模型其實(shí)可以理解為類文件系統(tǒng),如下圖:

1、ZNode 并不適合存儲(chǔ)太大的數(shù)據(jù)

為什么是類文件系統(tǒng)呢?因?yàn)?ZNode 模型沒有文件和文件夾的概念,每個(gè)節(jié)點(diǎn)既可以有子節(jié)點(diǎn),也可以存儲(chǔ)數(shù)據(jù)。

那么既然每個(gè)節(jié)點(diǎn)可以存儲(chǔ)數(shù)據(jù),是不是可以任意存儲(chǔ)無限制的數(shù)據(jù)呢?答案是否定的。在 Zookeeper 中,限制了每個(gè)節(jié)點(diǎn)只能存儲(chǔ)小于 1 M 的數(shù)據(jù),實(shí)際應(yīng)用中,最好不要超過 1kb。

原因有以下四點(diǎn):

  • 同步壓力:Zookeeper 的每個(gè)節(jié)點(diǎn)都存儲(chǔ)了 Zookeeper 的所有數(shù)據(jù),每個(gè)節(jié)點(diǎn)的狀態(tài)都要保持和 Leader 一致,同步過程至少要保證半數(shù)以上的節(jié)點(diǎn)同步成功,才算最終成功。如果數(shù)據(jù)越大,則寫入的難度也越大。
  • 請(qǐng)求阻塞:Zookeeper 為了保證寫入的強(qiáng)一致性,會(huì)嚴(yán)格按照寫入的順序串行執(zhí)行,某個(gè)時(shí)刻只能執(zhí)行一個(gè)事務(wù)。如果上一個(gè)事務(wù)執(zhí)行耗時(shí)比較長(zhǎng),會(huì)阻塞后面的請(qǐng)求;
  • 存儲(chǔ)壓力:正是因?yàn)槊總€(gè) Zookeeper 的節(jié)點(diǎn)都存儲(chǔ)了完整的數(shù)據(jù),每個(gè) ZNode 存儲(chǔ)的數(shù)據(jù)越大,則消耗的物理內(nèi)存也越大;
  • 設(shè)計(jì)初衷:Zookeeper 的設(shè)計(jì)初衷,不是為了提供大規(guī)模的存儲(chǔ)服務(wù),而是提供了這樣的數(shù)據(jù)模型解決一些分布式問題。

2、ZNode 的分類

(1)按生命周期分類

按照聲明周期,ZNode 可分為永久節(jié)點(diǎn)和臨時(shí)節(jié)點(diǎn)。

很好理解,永久節(jié)點(diǎn)就是要顯示的刪除,否則會(huì)一直存在;臨時(shí)節(jié)點(diǎn),是和會(huì)話綁定的,會(huì)話創(chuàng)建的所有節(jié)點(diǎn),會(huì)在會(huì)話斷開連接時(shí),全部被 Zookeeper 系統(tǒng)刪除。

(2)按照是否帶序列號(hào)分類

帶序列號(hào)的話,比如在代碼中創(chuàng)建 /a 節(jié)點(diǎn),創(chuàng)建之后其實(shí)是 /a000000000000001,再創(chuàng)建的話,就是 /a000000000000002,依次遞增

不帶序號(hào),就是創(chuàng)建什么就是什么

(3)所以,一共有四種 ZNode:

  • 永久的不帶序號(hào)的
  • 永久的帶序號(hào)的
  • 臨時(shí)的不帶序號(hào)的
  • 臨時(shí)的帶序號(hào)的

(4)注意的點(diǎn)

臨時(shí)節(jié)點(diǎn)下面不能掛載子節(jié)點(diǎn),只能作為其他節(jié)點(diǎn)的葉子節(jié)點(diǎn)。

3. 代碼實(shí)戰(zhàn)

ZNode 的數(shù)據(jù)模型其實(shí)很簡(jiǎn)單,只有這么多知識(shí)。下面用代碼來鞏固一下。

這里我們使用 curator 框架來做 demo。(當(dāng)然,你可以選擇使用 Zookeeper 官方自帶的 Api)

引入 pom 坐標(biāo):

  1. <!-- curator-framework --> 
  2. <dependency> 
  3.     <groupId>org.apache.curator</groupId> 
  4.     <artifactId>curator-framework</artifactId> 
  5.     <version>4.2.0</version> 
  6. </dependency> 
  7. <!-- curator-recipes --> 
  8. <dependency> 
  9.     <groupId>org.apache.curator</groupId> 
  10.     <artifactId>curator-recipes</artifactId> 
  11.     <version>4.2.0</version> 
  12. </dependency> 

代碼:

  1. public class ZkTest { 
  2.  
  3.     // 會(huì)話超時(shí) 
  4.     private final int SESSION_TIMEOUT = 30 * 1000; 
  5.  
  6.     // 連接超時(shí) 、 有啥區(qū)別 
  7.     private static final int CONNECTION_TIMEOUT = 3 * 1000; 
  8.  
  9.     private static final String CONNECT_ADDR = "localhost:2181"
  10.  
  11.     private CuratorFramework client = null
  12.  
  13.     public static void main(String[] args) throws Exception { 
  14.         // 創(chuàng)建客戶端 
  15.         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 10); 
  16.         CuratorFramework client = CuratorFrameworkFactory.builder() 
  17.                 .connectString(CONNECT_ADDR) 
  18.                 .connectionTimeoutMs(CONNECTION_TIMEOUT) 
  19.                 .retryPolicy(retryPolicy) 
  20.                 .build(); 
  21.         client.start(); 
  22.         System.out.println(ZooKeeper.States.CONNECTED); 
  23.         System.out.println(client.getState()); 
  24.  
  25.         // 創(chuàng)建節(jié)點(diǎn) /test1 
  26.         client.create() 
  27.                 .forPath("/test1""curator data".getBytes(StandardCharsets.UTF_8)); 
  28.  
  29.         System.out.println(client.getChildren().forPath("/")); 
  30.  
  31.         // 臨時(shí)節(jié)點(diǎn) 
  32.         client.create().withMode(CreateMode.EPHEMERAL) 
  33.                 .forPath("/secondPath""hello world".getBytes(StandardCharsets.UTF_8)); 
  34.         System.out.println(new String(client.getData().forPath("/secondPath"))); 
  35.  
  36.         client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL) 
  37.                 .forPath("/abc""hello".getBytes(StandardCharsets.UTF_8)); 
  38.         // 遞歸創(chuàng)建 
  39.         client.create() 
  40.                 .creatingParentContainersIfNeeded() 
  41.                 .forPath("/secondPath1/sencond2/sencond3"); 
  42.  
  43.  
  44.         Thread.sleep(10000); 
  45.     } 

四、核心機(jī)制二:Watcher 監(jiān)聽機(jī)制

Watcher 監(jiān)聽機(jī)制是 Zookeeper 解決各種分布式不一致疑難雜癥的獨(dú)家法門,也是學(xué)習(xí) Zookeeper 必學(xué)的知識(shí)點(diǎn)。

1. 對(duì)于 Watcher 機(jī)制的理解

Zookeeper 提供了數(shù)據(jù)的發(fā)布與訂閱的功能,多個(gè)訂閱者可以同時(shí)監(jiān)聽某一個(gè)對(duì)象,當(dāng)這個(gè)對(duì)象自身狀態(tài)發(fā)生變化時(shí)(例如節(jié)點(diǎn)數(shù)據(jù)或者節(jié)點(diǎn)的子節(jié)點(diǎn)個(gè)數(shù)變化),Zookeeper 系統(tǒng)會(huì)通知這些訂閱者。

對(duì)于發(fā)布和訂閱這個(gè)概念的理解,我們可以用這個(gè)場(chǎng)景來理解:

比如前兩天的臺(tái)風(fēng),老板想發(fā)一個(gè)通知給員工:明天在家辦公。

于是老板會(huì)在釘釘群上 Ding 一個(gè)消息,員工自己打開釘釘查看。

在這個(gè)場(chǎng)景中,老板是發(fā)布者,員工是訂閱者,釘釘群就是 Zookeeper 系統(tǒng)。

老板并不一一給員工發(fā)消息,而是把消息發(fā)到群里,員工就可以感知到消息的變化。

訂閱者 員工 客戶端1
系統(tǒng) 釘釘群 Zookeeper系統(tǒng)
發(fā)布者 老板 客戶端2

2、 Watcher 機(jī)制的流程

客戶端首先將 Watcher 注冊(cè)到服務(wù)器上,同時(shí)將 Watcher 對(duì)象保存在客戶端的 Watcher 管理器中。當(dāng) Zookeeper 服務(wù)端監(jiān)聽到數(shù)據(jù)狀態(tài)發(fā)生變化時(shí),服務(wù)端會(huì)首先主動(dòng)通知客戶端,接著客戶端的 Watcher 管理器會(huì)觸發(fā)相關(guān)的 Watcher 來回調(diào)響應(yīng)的邏輯,從而完成整體的發(fā)布/訂閱流程。

監(jiān)聽器 Watcher 的定義:

  1. public interface Watcher { 
  2. //   WatchedEvent 對(duì)象中有下面三個(gè)屬性,Zookeeper狀態(tài),事件類型,路徑 
  3. //    final private KeeperState keeperState; 
  4. //    final private EventType eventType; 
  5. //    private String path; 
  6.     abstract public void process(WatchedEvent event); 

下面是監(jiān)聽的大致流程圖:

稍稍解釋一下:

1、Client1 和 Client2 都關(guān)心 /app2 節(jié)點(diǎn)的數(shù)據(jù)狀態(tài)變化,于是注冊(cè)一個(gè)對(duì)于 /app2 的監(jiān)聽器到 Zookeeper 上;

2、當(dāng) Client3 修改 /app2 的值后,Zookeeper 會(huì)主動(dòng)通知 Client1 和 Client2 ,并且回調(diào)監(jiān)聽器的方法。

當(dāng)然這里的數(shù)據(jù)狀態(tài)變化有下面這些類型:

  • 節(jié)點(diǎn)被創(chuàng)建;
  • 節(jié)點(diǎn)被刪除;
  • 節(jié)點(diǎn)數(shù)據(jù)發(fā)生改變;
  • 節(jié)點(diǎn)的子節(jié)點(diǎn)個(gè)數(shù)發(fā)生改變。

3. 通過代碼來初步理解

我們還是用 Curator 框架來驗(yàn)證一下這個(gè)監(jiān)聽器。

代碼很簡(jiǎn)單,這里我們使用 TreeCache 表示對(duì)于 /app2 的監(jiān)聽,并且注冊(cè)了監(jiān)聽的方法。

  1. public class CuratorWatcher { 
  2.  
  3.     public static void main(String[] args) throws Exception { 
  4.         CuratorFramework client = CuratorFrameworkFactory.builder().connectString("localhost:2181"
  5.                 .connectionTimeoutMs(10000) 
  6.                 .retryPolicy(new ExponentialBackoffRetry(1000, 10)) 
  7.                 .build(); 
  8.         client.start(); 
  9.  
  10.         String path = "/app2"
  11.  
  12.         TreeCache treeCache = new TreeCache(client, path); 
  13.         treeCache.start(); 
  14.  
  15.         treeCache.getListenable().addListener((client1, event) -> { 
  16.             System.out.println("event.getData()," + event.getData()); 
  17.             System.out.println("event.getType()," + event.getType()); 
  18.         }); 
  19.  
  20.         Thread.sleep(Integer.MAX_VALUE); 
  21.     } 

當(dāng) /app2 的狀態(tài)發(fā)生變化時(shí),就會(huì)調(diào)用監(jiān)聽的方法。

Curator 是對(duì)原生的 Zookeeper Api 有封裝的,原生的 Zookeeper 提供的 Api ,注冊(cè)監(jiān)聽后,當(dāng)數(shù)據(jù)發(fā)生改變時(shí),監(jiān)聽就被服務(wù)端刪除了,要重復(fù)注冊(cè)監(jiān)聽。

Curator 則對(duì)這個(gè)做了相應(yīng)的封裝和改進(jìn)。

五、代碼實(shí)戰(zhàn):實(shí)現(xiàn)主備選舉

這里我們主要想實(shí)現(xiàn)的功能是:

  • 有兩個(gè)節(jié)點(diǎn),bigdata001,bigdata002 ,他們互相主備。
  • bigdata001 啟動(dòng)時(shí),往 zk 上注冊(cè)一個(gè)臨時(shí)節(jié)點(diǎn) /ElectorLock(鎖),并且往 /ActiveMaster 下面注冊(cè)一個(gè)子節(jié)點(diǎn),表示自己是主節(jié)點(diǎn)。
  • bigdata002 啟動(dòng)時(shí),發(fā)現(xiàn)臨時(shí)節(jié)點(diǎn) /ElectorLock 存在,表示當(dāng)前系統(tǒng)已經(jīng)有主節(jié)點(diǎn)了,則自己往 /StandbyMaster 下注冊(cè)一個(gè)節(jié)點(diǎn),表示自己是 standby。
  • bigdata001 退出時(shí),釋放 /ElectorLock,并且刪除 /activeMaster 下的節(jié)點(diǎn)。
  • bigdata002 感知到 /ElectorLock 不存在時(shí),則自己去注冊(cè) /ElectorLock,并在 /ActiveMaster 下注冊(cè)自己,表示自己已經(jīng)成為了主節(jié)點(diǎn)。

代碼還是用 Curator 框架實(shí)現(xiàn)的:

  1. package com.kkarch.zookeeper; 
  2.  
  3. import cn.hutool.core.util.StrUtil; 
  4. import lombok.extern.slf4j.Slf4j; 
  5. import org.apache.curator.framework.CuratorFramework; 
  6. import org.apache.curator.framework.recipes.cache.TreeCache; 
  7. import org.apache.curator.framework.recipes.cache.TreeCacheEvent; 
  8. import org.apache.zookeeper.CreateMode; 
  9.  
  10. import java.nio.charset.StandardCharsets; 
  11.  
  12. /** 
  13.  * 分布式選舉 
  14.  * 
  15.  * @Author wangkai 
  16.  * @Time 2021/7/25 20:12 
  17.  */ 
  18. @Slf4j 
  19. public class ElectorTest { 
  20.  
  21.     private static final String PARENT = "/cluster_ha"
  22.     private static final String ACTIVE = PARENT + "/ActiveMaster"
  23.     private static final String STANDBY = PARENT + "/StandbyMaster"
  24.     private static final String LOCK = PARENT + "/ElectorLock"
  25.  
  26.     private static final String HOSTNAME = "bigdata05"
  27.     private static final String activeMasterPath = ACTIVE + "/" + HOSTNAME; 
  28.     private static final String standByMasterPath = STANDBY + "/" + HOSTNAME; 
  29.  
  30.     public static void main(String[] args) throws Exception { 
  31.         CuratorFramework zk = ZkUtil.createZkClient("localhost:2181"); 
  32.         zk.start(); 
  33.  
  34.         // 注冊(cè)好監(jiān)聽 
  35.         TreeCache treeCache = new TreeCache(zk, PARENT); 
  36.         treeCache.start(); 
  37.  
  38.         treeCache.getListenable().addListener((client, event) -> { 
  39.             if (event.getType().equals(TreeCacheEvent.Type.INITIALIZED) || event.getType().equals(TreeCacheEvent.Type.CONNECTION_LOST) 
  40.                     || event.getType().equals(TreeCacheEvent.Type.CONNECTION_RECONNECTED) || event.getType().equals(TreeCacheEvent.Type.CONNECTION_SUSPENDED)) { 
  41.                 return
  42.             } 
  43.             System.out.println(event.getData()); 
  44.             // 如果 Active 下有節(jié)點(diǎn)被移除了,沒有節(jié)點(diǎn),則應(yīng)該去競(jìng)選成為 Active 
  45.             if (StrUtil.startWith(event.getData().getPath(), ACTIVE) && event.getType().equals(TreeCacheEvent.Type.NODE_REMOVED)) { 
  46.                 if (getChildrenNumber(zk, ACTIVE) == 0) { 
  47.                     createZNode(client, LOCK, HOSTNAME.getBytes(StandardCharsets.UTF_8), CreateMode.EPHEMERAL); 
  48.                     System.out.println(HOSTNAME + "爭(zhēng)搶到了鎖"); 
  49.                 } 
  50.             } 
  51.             // 如果有鎖節(jié)點(diǎn)被創(chuàng)建,則判斷是不是自己創(chuàng)建的,如果是,則切換自己的狀態(tài)為 ACTIVE 
  52.             else if (StrUtil.equals(event.getData().getPath(), LOCK) && event.getType().equals(TreeCacheEvent.Type.NODE_ADDED)) { 
  53.                 if (StrUtil.equals(new String(event.getData().getData()), HOSTNAME)) { 
  54.                     createZNode(zk, activeMasterPath, HOSTNAME.getBytes(StandardCharsets.UTF_8), CreateMode.EPHEMERAL); 
  55.                     if (checkExists(client, standByMasterPath)) { 
  56.                         deleteZNode(client, standByMasterPath); 
  57.                     } 
  58.                 } 
  59.             } 
  60.         }); 
  61.  
  62.         // 先創(chuàng)建 ACTIVE 和 STANDBY 節(jié)點(diǎn) 
  63.         if (zk.checkExists().forPath(ACTIVE) == null) { 
  64.             zk.create().creatingParentContainersIfNeeded().forPath(ACTIVE); 
  65.         } 
  66.         if (zk.checkExists().forPath(STANDBY) == null) { 
  67.             zk.create().creatingParentContainersIfNeeded().forPath(STANDBY); 
  68.         } 
  69.  
  70.         // 判斷 ACTIVE 下是否有子節(jié)點(diǎn),如果沒有則去爭(zhēng)搶一把鎖 
  71.         if (getChildrenNumber(zk, ACTIVE) == 0) { 
  72.             createZNode(zk, LOCK, HOSTNAME.getBytes(StandardCharsets.UTF_8), CreateMode.EPHEMERAL); 
  73.         } 
  74.         // 如果有,則自己成為 STANDBY 狀態(tài) 
  75.         else { 
  76.             createZNode(zk, standByMasterPath, HOSTNAME.getBytes(StandardCharsets.UTF_8), CreateMode.EPHEMERAL); 
  77.         } 
  78.  
  79.  
  80.         Thread.sleep(1000000000); 
  81.  
  82.  
  83.     } 
  84.  
  85.     public static int getChildrenNumber(CuratorFramework client, String path) throws Exception { 
  86.         return client.getChildren().forPath(path).size(); 
  87.     } 
  88.  
  89.     public static void createZNode(CuratorFramework client, String path, byte[] data, CreateMode mode) { 
  90.         try { 
  91.             client.create().withMode(mode).forPath(path, data); 
  92.         } catch (Exception e) { 
  93.             log.error("創(chuàng)建節(jié)點(diǎn)失敗", e); 
  94.             System.out.println("創(chuàng)建節(jié)點(diǎn)失敗了"); 
  95.         } 
  96.     } 
  97.  
  98.     public static boolean checkExists(CuratorFramework client, String path) throws Exception { 
  99.         return client.checkExists().forPath(path) != null
  100.     } 
  101.  
  102.     public static void deleteZNode(CuratorFramework client, String path) { 
  103.         try { 
  104.             if (checkExists(client, path)) { 
  105.                 client.delete().forPath(path); 
  106.             } 
  107.         } catch (Exception e) { 
  108.             log.error("刪除節(jié)點(diǎn)失敗", e); 
  109.         } 
  110.     } 

 

責(zé)任編輯:武曉燕 來源: KK架構(gòu)
相關(guān)推薦

2021-06-01 07:57:42

Zookeeper分布式系統(tǒng)

2012-11-06 13:58:26

分布式云計(jì)算分布式協(xié)同

2021-08-26 08:03:30

大數(shù)據(jù)Zookeeper選舉

2023-05-05 06:13:51

分布式多級(jí)緩存系統(tǒng)

2022-06-21 08:27:22

Seata分布式事務(wù)

2019-10-10 09:16:34

Zookeeper架構(gòu)分布式

2024-01-05 07:28:50

分布式事務(wù)框架

2023-02-23 07:55:41

2017-10-24 11:28:23

Zookeeper分布式鎖架構(gòu)

2021-10-25 10:21:59

ZK分布式鎖ZooKeeper

2024-07-29 09:57:47

2015-05-18 09:59:48

ZooKeeper分布式計(jì)算Hadoop

2025-05-15 08:05:00

2017-12-05 09:43:42

分布式系統(tǒng)核心

2021-02-28 07:49:28

Zookeeper分布式

2020-11-16 12:55:41

Redis分布式鎖Zookeeper

2021-07-16 07:57:34

ZooKeeperCurator源碼

2019-07-16 09:22:10

RedisZookeeper分布式鎖

2015-06-17 14:10:34

Redis分布式系統(tǒng)協(xié)調(diào)

2021-08-30 11:21:03

數(shù)據(jù)庫工具技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩中文一区二区三区 | www.嫩草| 久久精品国产一区 | 国产精品一区久久久久 | 成年男女免费视频网站 | 岛国精品 | 午夜成人免费视频 | 天天色图 | 日韩视频一区 | 亚洲3级 | 色成人免费网站 | 亚洲一区在线日韩在线深爱 | 久久婷婷香蕉热狠狠综合 | 久热爱 | 日韩中文字幕一区二区 | 亚洲成人av | 午夜视频网 | av黄色在线观看 | 免费久久精品视频 | 91视频大全| 91精品国产91久久综合桃花 | www亚洲精品| 亚洲97| 成人av网站在线观看 | 久久99这里只有精品 | 91视频在线看 | 欧美在线a | 自拍偷拍3p| 亚洲综合视频 | 日韩中文一区二区三区 | 亚洲精品粉嫩美女一区 | www久久国产| 韩日一区二区三区 | 国产视频精品在线 | 91精品国产欧美一区二区成人 | 久久天天综合 | 国产91精品久久久久久久网曝门 | 国产一级在线观看 | 亚洲精品久久久久中文字幕欢迎你 | 国产精品欧美一区二区三区不卡 | www97影院|