分布式--ZooKeeper 分布式服務(wù)協(xié)同

1. ZooKeeper官方

1). 簡(jiǎn)介

ZooKeeper是一個(gè)分布式的,開(kāi)放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Google的Chubby一個(gè)開(kāi)源的實(shí)現(xiàn),是Hadoop和Hbase的重要組件。它是一個(gè)為分布式應(yīng)用提供一致性服務(wù)的軟件,提供的功能包括:配置維護(hù)、域名服務(wù)、分布式同步、組服務(wù)等。
ZooKeeper的目標(biāo)就是封裝好復(fù)雜易出錯(cuò)的關(guān)鍵服務(wù),將簡(jiǎn)單易用的接口和性能高效、功能穩(wěn)定的系統(tǒng)提供給用戶。ZooKeeper包含一個(gè)簡(jiǎn)單的原語(yǔ)集,提供Java和C的接口。
ZooKeeper代碼版本中,提供了分布式獨(dú)享鎖、選舉、隊(duì)列的接口,代碼在zookeeper-3.4.8\src\recipes。其中分布鎖和隊(duì)列有Java和C兩個(gè)版本,選舉只有Java版本。

2). ZooKeeper下載
圖1.png
3). 分布式應(yīng)用
圖2.png
4). 優(yōu)點(diǎn)及挑戰(zhàn)
  • 分布式應(yīng)用的優(yōu)點(diǎn)

    • 可靠性 - 單個(gè)或幾個(gè)系統(tǒng)的故障不會(huì)使整個(gè)系統(tǒng)出現(xiàn)故障。
    • 可擴(kuò)展性 - 可以在需要時(shí)增加性能,通過(guò)添加更多機(jī)器,在應(yīng)用程序配置中進(jìn)行微小的更改,而不會(huì)有停機(jī)時(shí)間。
    • 透明性 - 隱藏系統(tǒng)的復(fù)雜性,并將其顯示為單個(gè)實(shí)體/應(yīng)用程序。
  • 分布式應(yīng)用的挑戰(zhàn)

    • 競(jìng)爭(zhēng)條件 - 兩個(gè)或多個(gè)機(jī)器嘗試執(zhí)行特定任務(wù),實(shí)際上只需在任意給定時(shí)間由單個(gè)機(jī)器完成。例如,共享資源只能在任意給定時(shí)間由單個(gè)機(jī)器修改。
    • 死鎖 - 兩個(gè)或多個(gè)操作等待彼此無(wú)限期完成。
    • 不一致 - 數(shù)據(jù)的部分失敗。
5). ZooKeeper描述

Apache ZooKeeper是由集群(節(jié)點(diǎn)組)使用的一種服務(wù),用于在自身之間協(xié)調(diào),并通過(guò)穩(wěn)健的同步技術(shù)維護(hù)共享數(shù)據(jù)。ZooKeeper本身是一個(gè)分布式應(yīng)用程序,為寫(xiě)入分布式應(yīng)用程序提供服務(wù)。
ZooKeeper提供的常見(jiàn)服務(wù)如下 :

  • 命名服務(wù) - 按名稱標(biāo)識(shí)集群中的節(jié)點(diǎn)。它類似于DNS,但僅對(duì)于節(jié)點(diǎn)。
  • 配置管理 - 加入節(jié)點(diǎn)的最近的和最新的系統(tǒng)配置信息。
  • 集群管理 - 實(shí)時(shí)地在集群和節(jié)點(diǎn)狀態(tài)中加入/離開(kāi)節(jié)點(diǎn)。
  • 選舉算法 - 選舉一個(gè)節(jié)點(diǎn)作為協(xié)調(diào)目的的leader。
  • 鎖定和同步服務(wù) - 在修改數(shù)據(jù)的同時(shí)鎖定數(shù)據(jù)。此機(jī)制可幫助你在連接其他分布式應(yīng)用程序(如Apache HBase)時(shí)進(jìn)行自動(dòng)故障恢復(fù)。
  • 高度可靠的數(shù)據(jù)注冊(cè)表 - 即使在一個(gè)或幾個(gè)節(jié)點(diǎn)關(guān)閉時(shí)也可以獲得數(shù)據(jù)。
6). 工作流

一旦ZooKeeper集合啟動(dòng),它將等待客戶端連接。客戶端將連接到ZooKeeper集合中的一個(gè)節(jié)點(diǎn)。它可以是leader或follower節(jié)點(diǎn)。一旦客戶端被連接,節(jié)點(diǎn)將向特定客戶端分配會(huì)話ID并向該客戶端發(fā)送確認(rèn)。如果客戶端沒(méi)有收到確認(rèn),它將嘗試連接ZooKeeper集合中的另一個(gè)節(jié)點(diǎn)。 一旦連接到節(jié)點(diǎn),客戶端將以有規(guī)律的間隔向節(jié)點(diǎn)發(fā)送心跳,以確保連接不會(huì)丟失。

  • 如果客戶端想要讀取特定的znode,它將會(huì)向具有znode路徑的節(jié)點(diǎn)發(fā)送讀取請(qǐng)求,并且節(jié)點(diǎn)通過(guò)從其自己的數(shù)據(jù)庫(kù)獲取來(lái)返回所請(qǐng)求的znode。為此,在ZooKeeper集合中讀取速度很快。
  • 如果客戶端想要將數(shù)據(jù)存儲(chǔ)在ZooKeeper集合中,則會(huì)將znode路徑和數(shù)據(jù)發(fā)送到服務(wù)器。連接的服務(wù)器將該請(qǐng)求轉(zhuǎn)發(fā)給leader,然后leader將向所有的follower重新發(fā)出寫(xiě)入請(qǐng)求。如果只有大部分節(jié)點(diǎn)成功響應(yīng),而寫(xiě)入請(qǐng)求成功,則成功返回代碼將被發(fā)送到客戶端。 否則,寫(xiě)入請(qǐng)求失敗。絕大多數(shù)節(jié)點(diǎn)被稱為 Quorum 。
7). 節(jié)點(diǎn)

讓我們分析在ZooKeeper集合中擁有不同數(shù)量的節(jié)點(diǎn)的效果。

  • 如果我們有單個(gè)節(jié)點(diǎn),則當(dāng)該節(jié)點(diǎn)故障時(shí),ZooKeeper集合將故障。它有助于“單點(diǎn)故障",不建議在生產(chǎn)環(huán)境中使用。
  • 如果我們有兩個(gè)節(jié)點(diǎn)而一個(gè)節(jié)點(diǎn)故障,我們沒(méi)有占多數(shù),因?yàn)閮蓚€(gè)中的一個(gè)不是多數(shù)。
  • 如果我們有三個(gè)節(jié)點(diǎn)而一個(gè)節(jié)點(diǎn)故障,那么我們有大多數(shù),因此,這是最低要求。ZooKeeper集合在實(shí)際生產(chǎn)環(huán)境中必須至少有三個(gè)節(jié)點(diǎn)。
  • 如果我們有四個(gè)節(jié)點(diǎn)而兩個(gè)節(jié)點(diǎn)故障,它將再次故障。類似于有三個(gè)節(jié)點(diǎn),額外節(jié)點(diǎn)不用于任何目的,因此,最好添加奇數(shù)的節(jié)點(diǎn),例如3,5,7。


    圖3.png
組件 描述
寫(xiě)入(write) 寫(xiě)入過(guò)程由leader節(jié)點(diǎn)處理。leader將寫(xiě)入請(qǐng)求轉(zhuǎn)發(fā)到所有znode,并等待znode的回復(fù)。如果一半的znode回復(fù),則寫(xiě)入過(guò)程完成。
讀?。╮ead) 讀取由特定連接的znode在內(nèi)部執(zhí)行,因此不需要與集群進(jìn)行交互。
復(fù)制數(shù)據(jù)庫(kù)(replicated database) 它用于在zookeeper中存儲(chǔ)數(shù)據(jù)。每個(gè)znode都有自己的數(shù)據(jù)庫(kù),每個(gè)znode在一致性的幫助下每次都有相同的數(shù)據(jù)。
Leader Leader是負(fù)責(zé)處理寫(xiě)入請(qǐng)求的Znode。
Follower follower從客戶端接收寫(xiě)入請(qǐng)求,并將它們轉(zhuǎn)發(fā)到leader znode。
請(qǐng)求處理器(request processor) 只存在于leader節(jié)點(diǎn)。它管理來(lái)自follower節(jié)點(diǎn)的寫(xiě)入請(qǐng)求。
原子廣播(atomic broadcasts) 負(fù)責(zé)廣播從leader節(jié)點(diǎn)到follower節(jié)點(diǎn)的變化。

2. 安裝

1). 修改/conf/zoo_sample.cfg配置文件

I. 修改文件名zoo_sample.cfg為zoo.cfg.


圖4.png

II. 修改zoo.cfg文件內(nèi)容

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=D:\\zookeeper-3.4.10.tar\\zookeeper-3.4.10\\data
dataLogDir=D:\\zookeeper-3.4.10.tar\\zookeeper-3.4.10\\log
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

III. 配置文件解析

  • tickTime:這個(gè)時(shí)間是作為 Zookeeper 服務(wù)器之間或客戶端與服務(wù)器之間維持心跳的時(shí)間間隔,也就是每個(gè) tickTime 時(shí)間就會(huì)發(fā)送一個(gè)心跳。
  • dataDir:顧名思義就是 Zookeeper 保存數(shù)據(jù)的目錄,默認(rèn)情況下,Zookeeper 將寫(xiě)數(shù)據(jù)的日志文件也保存在這個(gè)目錄里。
  • dataLogDir:顧名思義就是 Zookeeper 保存日志文件的目錄
  • clientPort:這個(gè)端口就是客戶端連接 Zookeeper 服務(wù)器的端口,Zookeeper 會(huì)監(jiān)聽(tīng)這個(gè)端口,接受客戶端的訪問(wèn)請(qǐng)求。
2). 啟動(dòng)
  • 進(jìn)入到bin目錄,并且啟動(dòng)zkServer.cmd,這時(shí)會(huì)啟動(dòng)一個(gè)java進(jìn)程
zkServer.cmd
圖5.png
  • 查看進(jìn)程
jps -l -v
圖6.png
  • 客戶端連接
zkCli.cmd 127.0.0.1:2181
圖7.png

3. API代碼測(cè)試

1). 基礎(chǔ)知識(shí)

與ZooKeeper集合進(jìn)行交互的應(yīng)用程序稱為 ZooKeeper客戶端或簡(jiǎn)稱客戶端。
Znode是ZooKeeper集合的核心組件,ZooKeeper API提供了一小組方法使用ZooKeeper集合來(lái)操縱znode的所有細(xì)節(jié)。
客戶端應(yīng)該遵循以步驟,與ZooKeeper集合進(jìn)行清晰和干凈的交互。

  • 連接到ZooKeeper集合。ZooKeeper集合為客戶端分配會(huì)話ID。
  • 定期向服務(wù)器發(fā)送心跳。否則,ZooKeeper集合將過(guò)期會(huì)話ID,客戶端需要重新連接。
  • 只要會(huì)話ID處于活動(dòng)狀態(tài),就可以獲取/設(shè)置znode。
  • 所有任務(wù)完成后,斷開(kāi)與ZooKeeper集合的連接。如果客戶端長(zhǎng)時(shí)間不活動(dòng),則ZooKeeper集合將自動(dòng)斷開(kāi)客戶端。
2). API

ZooKeeper API的核心部分是ZooKeeper類。它提供了在其構(gòu)造函數(shù)中連接ZooKeeper集合的選項(xiàng),并具有以下方法:

  • connect - 連接到ZooKeeper集合
  • create- 創(chuàng)建znode
  • exists- 檢查znode是否存在及其信息
  • getData - 從特定的znode獲取數(shù)據(jù)
  • setData - 在特定的znode中設(shè)置數(shù)據(jù)
  • getChildren - 獲取特定znode中的所有子節(jié)點(diǎn)
  • delete - 刪除特定的znode及其所有子項(xiàng)
  • close - 關(guān)閉連接

新建Java工程,并導(dǎo)入/lib/log4j-1.2.16.jar、/lib/slf4j-api-1.6.1.jar、/lib/slf4j-log4j12-1.6.1.jar、zookeeper-3.4.10.jar,將/conf/路徑下的log4j.properties文件拷貝到項(xiàng)目的src目錄下


圖8.png
3). connect(連接到ZooKeeper集合)

I. 方法原型

ZooKeeper(String connectionString, int sessionTimeout, Watcher watcher)
  • connectionString - ZooKeeper集合主機(jī)。
  • sessionTimeout - 會(huì)話超時(shí)(以毫秒為單位)。
  • watcher - 實(shí)現(xiàn)“監(jiān)視器”界面的對(duì)象。ZooKeeper集合通過(guò)監(jiān)視器對(duì)象返回連接狀態(tài)。
    II. 代碼
/**
 * ZooKeeper連接管理
 * @author mazaiting
 */
public class ZooKeeperConnection {

    /**
     * 定義ZooKeeper實(shí)例
     */
    private ZooKeeper zooKeeper;
    /**
     * 用戶停止(等待)主線程,直到客戶端與ZooKeeper集合連接
     */
    private final CountDownLatch connectedSignal = new CountDownLatch(1);
    
    /**
     * 連接
     * @param host 主機(jī)地址
     * @return ZooKeeper對(duì)象
     * @throws IOException IO異常
     * @throws InterruptedException 中斷異常
     */
    public ZooKeeper connect(String host) throws IOException, InterruptedException {
        // 創(chuàng)建ZooKeeper對(duì)象
        zooKeeper = new ZooKeeper(host, 5000, new Watcher(){
            /**
             * 
             */
            @Override
            public void process(WatchedEvent event) {
                if (event.getState() == KeeperState.SyncConnected) {
                    connectedSignal.countDown();
                }
            }
        });
        // 等待
        connectedSignal.await();
        return zooKeeper;
    }
    
    /**
     * 關(guān)機(jī)ZooKeeper的連接
     * @throws InterruptedException 中斷異常
     */
    public void close() throws InterruptedException {
        zooKeeper.close();
    }
}
4). create(創(chuàng)建znode)

I. 方法原型

create(String path, byte[] data, List<ACL> acl, CreateMode createMode)
  • path - Znode路徑。例如,/myapp1,/myapp2,/myapp1/mydata1,myapp2/mydata1/myanothersubdata
  • data - 要存儲(chǔ)在指定znode路徑中的數(shù)據(jù)
  • acl - 要?jiǎng)?chuàng)建的節(jié)點(diǎn)的訪問(wèn)控制列表。ZooKeeper API提供了一個(gè)靜態(tài)接口 ZooDefs.Ids 來(lái)獲取一些基本的acl列表。例如,ZooDefs.Ids.OPEN_ACL_UNSAFE返回打開(kāi)znode的acl列表。
  • createMode - 節(jié)點(diǎn)的類型,即臨時(shí),順序或兩者。這是一個(gè)枚舉。

II. 代碼

/**
 * 創(chuàng)建節(jié)點(diǎn)
 * @author mazaiting
 */
public class ZKCreate {
    /**
     * 創(chuàng)建靜態(tài)的ZooKeeper實(shí)例
     */
    private static ZooKeeper zooKeeper;
    /**
     * 創(chuàng)建靜態(tài)的連接實(shí)例
     */
    private static ZooKeeperConnection conn;
    
    /**
     * 創(chuàng)建節(jié)點(diǎn)
     * @param path Znode路徑
     * @param data 存儲(chǔ)在Znode路徑中的數(shù)據(jù)
     * @throws KeeperException ZooKeeper異常
     * @throws InterruptedException 中斷異常
     */
    public static void create(String path, byte[] data) throws KeeperException, InterruptedException {
        zooKeeper.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }
    
    public static void main(String[] args) {
        // znode路徑
        String path = "/MyFirst";
        // 二進(jìn)制數(shù)據(jù)
        byte[] data = "My First ZooKeeper app".getBytes();
        
        try {
            // 創(chuàng)建連接對(duì)象
            conn = new ZooKeeperConnection();
            // 連接, 并返回ZooKeeper
            zooKeeper = conn.connect("127.0.0.1");
            // 創(chuàng)建Znode
            create(path, data);
            // 關(guān)閉
            conn.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
    
}

III. 測(cè)試

  • 執(zhí)行結(jié)果:


    圖9.png
  • 獲取數(shù)據(jù):在命令提示符中使用zkCli.cmd開(kāi)啟一個(gè)客戶端窗口,
    圖10.png

    連接成功后, 輸入get /MyFirst(get 路徑名)查看數(shù)據(jù)
    圖10.png
5). exists(檢查znode是否存在及其信息)

I. 方法原型

exists(String path, boolean watcher)
  • path- Znode路徑
  • watcher - 布爾值,用于指定是否監(jiān)視指定的znode
    II. 代碼
/**
 * 判斷某個(gè)路徑是否存在
 * @author mazaiting
 */
public class ZKExists {
    /**
     * 定義靜態(tài)的ZooKeeper對(duì)象
     */
    private static ZooKeeper zooKeeper;
    /**
     * 定義靜態(tài)的ZooKeeper連接對(duì)象
     */
    private static ZooKeeperConnection conn;
    
    /**
     * 判斷某個(gè)路徑是否存在
     * @param path 路徑
     * @return 返回狀態(tài)
     * @throws KeeperException ZooKeeper異常
     * @throws InterruptedException 中斷異常
     */
    public static Stat exists(String path) throws KeeperException, InterruptedException {
        return zooKeeper.exists(path, true);
    }
    
    public static void main(String[] args) {
        // znode路徑
        String path = "/MyFirst";       
        try {
            // 創(chuàng)建連接對(duì)象
            conn = new ZooKeeperConnection();
            // 連接, 并返回ZooKeeper
            zooKeeper = conn.connect("127.0.0.1");
            // 檢測(cè)路徑是否存在
            Stat stat = exists(path);
            // 判斷是否為空
            if (null != stat) {
                // 存在打印其版本信息
                System.out.println("Node exists and the node version is " + stat.getVersion());
            } else {
                System.out.println("Node does not exists");
            }
            // 關(guān)閉
            conn.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

III. 測(cè)試


圖11.png
6). getData(從特定的znode獲取數(shù)據(jù))

I. 方法原型

getData(String path, Watcher watcher, Stat stat)
  • path - Znode路徑。
  • watcher - 監(jiān)視器類型的回調(diào)函數(shù)。當(dāng)指定的znode的數(shù)據(jù)改變時(shí),ZooKeeper集合將通過(guò)監(jiān)視器回調(diào)進(jìn)行通知。這是一次性通知。
  • stat - 返回znode的元數(shù)據(jù)。

II. 代碼

/**
 * 獲取數(shù)據(jù)
 * @author mazaiting
 */
public class ZKGetData {
    /**
     * 定義靜態(tài)的ZooKeeper對(duì)象
     */
    private static ZooKeeper zooKeeper;
    /**
     * 定義靜態(tài)的ZooKeeper連接對(duì)象
     */
    private static ZooKeeperConnection conn;
    
    /**
     * 判斷某個(gè)路徑是否存在
     * @param path 路徑
     * @return 返回狀態(tài)
     * @throws KeeperException ZooKeeper異常
     * @throws InterruptedException 中斷異常
     */
    public static Stat exists(String path) throws KeeperException, InterruptedException {
        return zooKeeper.exists(path, true);
    }
    
    public static void main(String[] args) {
        // 路徑
        String path = "/MyFirst";
        // 用戶停止(等待)主線程,直到客戶端知道獲取到數(shù)據(jù)
        final CountDownLatch connectedSignal = new CountDownLatch(1);
        try {
            // 創(chuàng)建連接對(duì)象
            conn = new ZooKeeperConnection();
            // 連接
            zooKeeper = conn.connect("127.0.0.1");
            // 檢測(cè)是否存此路徑
            Stat stat = exists(path);
            // 判斷是否存在
            if (null != stat) {
                // 獲取字節(jié)數(shù)組
                byte[] bytes = zooKeeper.getData(path, new Watcher() {
                    
                    @Override
                    public void process(WatchedEvent event) {
                        // 檢測(cè)狀態(tài)
                        if (Event.EventType.None == event.getType()) {
                            // 判斷狀態(tài)
                            switch (event.getState()) {
                            case Expired:
                                // 關(guān)閉
                                connectedSignal.countDown();
                                break;

                            default:
                                break;
                            }
                        } else {
                            try {
                                byte[] bn = zooKeeper.getData(path, false, null);
                                // 將字節(jié)數(shù)組轉(zhuǎn)換為字符創(chuàng)
                                String data = new String(bn, "UTF-8");
                                // 打印字符串
                                System.out.println(data);
                                // 關(guān)閉
                                connectedSignal.countDown();
                            } catch (Exception e) {
                                // 打印錯(cuò)誤日志
                                System.out.println(e.getMessage());
                            }
                        }
                    }
                }, null);
                // 將字節(jié)數(shù)組轉(zhuǎn)換為字符創(chuàng)
                String data = new String(bytes, "UTF-8");
                // 打印字符串
                System.out.println(data);
                // 等待
                connectedSignal.await();
            } else {
                // 節(jié)點(diǎn)不存在
                System.out.println("Node does not exists");
            }
        } catch (Exception e) {
            // 打印錯(cuò)誤日志
            System.out.println(e.getMessage());
        }
    }
}

III. 測(cè)試


圖12.png
7). setData(在特定的znode中設(shè)置數(shù)據(jù))

I. 方法原型

setData(String path, byte[] data, int version)
  • path- Znode路徑。
  • data - 要存儲(chǔ)在指定znode路徑中的數(shù)據(jù)。
  • version- znode的當(dāng)前版本。每當(dāng)數(shù)據(jù)更改時(shí),ZooKeeper會(huì)更新znode的版本號(hào)。
    II. 代碼
/**
 * 設(shè)置數(shù)據(jù)
 * @author mazaiting
 */
public class ZKSetData {

    /**
     * 定義靜態(tài)的ZooKeeper對(duì)象
     */
    private static ZooKeeper zooKeeper;
    /**
     * 定義靜態(tài)的ZooKeeper連接對(duì)象
     */
    private static ZooKeeperConnection conn;
    
    /**
     * 更新數(shù)據(jù)
     * @param path 路徑
     * @param data 二進(jìn)制數(shù)據(jù)
     * @throws KeeperException ZooKeeper異常
     * @throws InterruptedException 中斷異常
     */
    public static void update(String path, byte[] data) throws KeeperException, InterruptedException {
        zooKeeper.setData(path, data, zooKeeper.exists(path, true).getVersion());
    }
    
    public static void main(String[] args) {
        // 路徑
        String path = "/MyFirst";
        // 二進(jìn)制數(shù)據(jù)
        byte[] data = "Success".getBytes();
        try {
            // 創(chuàng)建連接對(duì)象
            conn = new ZooKeeperConnection();
            // 連接并獲取ZooKeeper
            zooKeeper = conn.connect("127.0.0.1");
            // 更新數(shù)據(jù)
            update(path, data);
        } catch (Exception e) {
            // 打印錯(cuò)誤信息
            System.out.println(e.getMessage());
        }
    }
}

III. 測(cè)試
運(yùn)行程序后,在命令提示符中使用zkCli.cmd開(kāi)啟一個(gè)客戶端窗口,連接成功后, 輸入get /MyFirst(get 路徑名)查看數(shù)據(jù)

圖13.png

8). getChildren(獲取特定znode中的所有子節(jié)點(diǎn))

I. 方法原型

getChildren(String path, Watcher watcher)
  • path - Znode路徑。
  • watcher - 監(jiān)視器類型的回調(diào)函數(shù)。當(dāng)指定的znode被刪除或znode下的子節(jié)點(diǎn)被創(chuàng)建/刪除時(shí),ZooKeeper集合將進(jìn)行通知。這是一次性通知。
    II. 代碼
/**
 * 獲取子節(jié)點(diǎn)
 * @author mazaiting
 */
public class ZKGetChildren {

    /**
     * 定義靜態(tài)的ZooKeeper對(duì)象
     */
    private static ZooKeeper zooKeeper;
    /**
     * 定義靜態(tài)的ZooKeeper連接對(duì)象
     */
    private static ZooKeeperConnection conn;
    
    /**
     * 判斷某個(gè)路徑是否存在
     * @param path 路徑
     * @return 返回狀態(tài)
     * @throws KeeperException ZooKeeper異常
     * @throws InterruptedException 中斷異常
     */
    public static Stat exists(String path) throws KeeperException, InterruptedException {
        return zooKeeper.exists(path, true);
    }
    
    public static void main(String[] args) {
        // 路徑
        String path = "/MyFirst";
        try {
            // 創(chuàng)建連接對(duì)象
            conn = new ZooKeeperConnection();
            // 連接,并獲取ZooKeeper對(duì)象
            zooKeeper = conn.connect("127.0.0.1");
            // 判斷路徑是否存在
            Stat stat = exists(path);
            // 判斷是否為空
            if (null != stat) {
                // 獲取孩子列表
                List<String> children = zooKeeper.getChildren(path, false);
                // 遍歷孩子列表
                for(int i = 0; i < children.size(); i++) {
                    // 打印數(shù)據(jù)
                    System.out.println(children.get(i));
                }
            } else {
                // 路徑不存在
                System.out.println("Node does not exists");
            }
        } catch (Exception e) {
            // 打印錯(cuò)誤信息
            System.out.println(e.getMessage());
        }
    }
}

III. 測(cè)試

  • 先在命令提示符窗口中添加兩個(gè)孩子節(jié)點(diǎn)


    圖14.png
  • 運(yùn)行項(xiàng)目


    圖15.png
9). delete(刪除特定的znode及其所有子項(xiàng))

I. 方法原型

delete(String path, int version)
  • path - Znode路徑。
  • version - znode的當(dāng)前版本。
    II. 代碼
/**
 * 刪除路徑
 * @author mazaiting
 */
public class ZKDelete {

    /**
     * 定義靜態(tài)的ZooKeeper對(duì)象
     */
    private static ZooKeeper zooKeeper;
    /**
     * 定義靜態(tài)的ZooKeeper連接對(duì)象
     */
    private static ZooKeeperConnection conn;
    
    /**
     * 刪除節(jié)點(diǎn)
     * @param path 路徑
     * @throws InterruptedException 中斷異常
     * @throws KeeperException ZooKeeper異常
     */
    public static void delete(String path) throws InterruptedException, KeeperException {
        zooKeeper.delete(path, zooKeeper.exists(path, true).getVersion());
    }
    
    public static void main(String[] args) {
        // 路徑
        String path = "/MyFirst/first";
        try {
            // 創(chuàng)建ZooKeeper連接
            conn = new ZooKeeperConnection();
            // 連接
            zooKeeper = conn.connect("127.0.0.1");
            // 刪除
            delete(path);
        } catch (Exception e) {
            // 打印錯(cuò)誤信息
            System.out.println(e.getMessage());
        }
    }
}

III. 測(cè)試
刪除前/MyFirst的numChildren量比刪除后多1


圖16.png

代碼下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容