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下載

3). 分布式應(yīng)用

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.

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

- 查看進(jìn)程
jps -l -v

- 客戶端連接
zkCli.cmd 127.0.0.1:2181

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目錄下

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è)試

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è)試

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ù)

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






