1. 前言
這篇文章簡單給演示一下 ZooKeeper 常見命令的使用以及 ZooKeeper Java客戶端 Curator 的基本使用。介紹到的內容都是最基本的操作,能滿足日常工作的基本需要。
如果文章有任何需要改善和完善的地方,歡迎在評論區指出,共同進步!
2. ZooKeeper 安裝和使用
2.1. 使用Docker 安裝 zookeeper
a.使用 Docker 下載 ZooKeeper
docker pull zookeeper:3.5.8
b.運行 ZooKeeper
docker run -d --name zookeeper -p 2181:2181 zookeeper:3.5.8
2.2. 連接 ZooKeeper 服務
a.進入ZooKeeper容器中
先使用 docker ps
查看 ZooKeeper 的 ContainerID,然后使用 docker exec -it ContainerID /bin/bash
命令進入容器中。
b.先進入 bin 目錄,然后通過 ./zkCli.sh -server 127.0.0.1:2181
命令連接ZooKeeper 服務
root@eaf70fc620cb:/apache-zookeeper-3.5.8-bin# cd bin
如果你看到控制台成功打印出如下信息的話,說明你已經成功連接 ZooKeeper 服務。
2.3. 常用命令演示
2.3.1. 查看常用命令(help 命令)
通過 help
命令查看 ZooKeeper 常用命令
2.3.2. 創建節點(create 命令)
通過 create
命令在根目錄創建了 node1 節點,與它關聯的字符串是"node1"
[zk: 127.0.0.1:2181(CONNECTED) 34] create /node1 “node1”
通過 create
命令在根目錄創建了 node1 節點,與它關聯的內容是數字 123
[zk: 127.0.0.1:2181(CONNECTED) 1] create /node1/node1.1 123
Created /node1/node1.1
2.3.3. 更新節點數據內容(set 命令)
[zk: 127.0.0.1:2181(CONNECTED) 11] set /node1 "set node1"
2.3.4. 獲取節點的數據(get 命令)
get
命令可以獲取指定節點的數據內容和節點的狀態,可以看出我們通過 set
命令已經將節點數據內容改為 "set node1"。
set node1
cZxid = 0x47
ctime = Sun Jan 20 10:22:59 CST 2019
mZxid = 0x4b
mtime = Sun Jan 20 10:41:10 CST 2019
pZxid = 0x4a
cversion = 1
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 1
2.3.5. 查看某個目錄下的子節點(ls 命令)
通過 ls
命令查看根目錄下的節點
[zk: 127.0.0.1:2181(CONNECTED) 37] ls /
[dubbo, ZooKeeper, node1]
通過 ls
命令查看 node1 目錄下的節點
[zk: 127.0.0.1:2181(CONNECTED) 5] ls /node1
[node1.1]
ZooKeeper 中的 ls 命令和 linux 命令中的 ls 類似, 這個命令將列出絕對路徑 path 下的所有子節點信息(列出 1 級,並不遞歸)
2.3.6. 查看節點狀態(stat 命令)
通過 stat
命令查看節點狀態
[zk: 127.0.0.1:2181(CONNECTED) 10] stat /node1
cZxid = 0x47
ctime = Sun Jan 20 10:22:59 CST 2019
mZxid = 0x47
mtime = Sun Jan 20 10:22:59 CST 2019
pZxid = 0x4a
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 1
上面顯示的一些信息比如 cversion、aclVersion、numChildren 等等,我在上面 “znode(數據節點)的結構” 這部分已經介紹到。
2.3.7. 查看節點信息和狀態(ls2 命令)
ls2
命令更像是 ls
命令和 stat
命令的結合。 ls2
命令返回的信息包括 2 部分:
- 子節點列表
- 當前節點的 stat 信息。
[zk: 127.0.0.1:2181(CONNECTED) 7] ls2 /node1
[node1.1]
cZxid = 0x47
ctime = Sun Jan 20 10:22:59 CST 2019
mZxid = 0x47
mtime = Sun Jan 20 10:22:59 CST 2019
pZxid = 0x4a
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 1
2.3.8. 刪除節點(delete 命令)
這個命令很簡單,但是需要注意的一點是如果你要刪除某一個節點,那么這個節點必須無子節點才行。
[zk: 127.0.0.1:2181(CONNECTED) 3] delete /node1/node1.1
在后面我會介紹到 Java 客戶端 API 的使用以及開源 ZooKeeper 客戶端 ZkClient 和 Curator 的使用。
3. ZooKeeper Java客戶端 Curator簡單使用
Curator 是Netflix公司開源的一套 ZooKeeper Java客戶端框架,相比於 Zookeeper 自帶的客戶端 zookeeper 來說,Curator 的封裝更加完善,各種 API 都可以比較方便地使用。
下面我們就來簡單地演示一下 Curator 的使用吧!
Curator4.0+版本對ZooKeeper 3.5.x支持比較好。開始之前,請先將下面的依賴添加進你的項目。
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
3.1. 連接 ZooKeeper 客戶端
通過 CuratorFrameworkFactory
創建 CuratorFramework
對象,然后再調用 CuratorFramework
對象的 start()
方法即可!
private static final int BASE_SLEEP_TIME = 1000;
private static final int MAX_RETRIES = 3;
// Retry strategy. Retry 3 times, and will increase the sleep time between retries.
RetryPolicy retryPolicy = new ExponentialBackoffRetry(BASE_SLEEP_TIME, MAX_RETRIES);
CuratorFramework zkClient = CuratorFrameworkFactory.builder()
// the server to connect to (can be a server list)
.connectString("127.0.0.1:2181")
.retryPolicy(retryPolicy)
.build();
zkClient.start();
對於一些基本參數的說明:
baseSleepTimeMs
:重試之間等待的初始時間maxRetries
:最大重試次數connectString
:要連接的服務器列表retryPolicy
:重試策略
3.2. 數據節點的增刪改查
3.2.1. 創建節點
我們在 ZooKeeper常見概念解讀 中介紹到,我們通常是將 znode 分為 4 大類:
- 持久(PERSISTENT)節點 :一旦創建就一直存在即使 ZooKeeper 集群宕機,直到將其刪除。
- 臨時(EPHEMERAL)節點 :臨時節點的生命周期是與 客戶端會話(session) 綁定的,會話消失則節點消失 。並且,臨時節點 只能做葉子節點 ,不能創建子節點。
- 持久順序(PERSISTENT_SEQUENTIAL)節點 :除了具有持久(PERSISTENT)節點的特性之外, 子節點的名稱還具有順序性。比如
/node1/app0000000001
、/node1/app0000000002
。 - 臨時順序(EPHEMERAL_SEQUENTIAL)節點 :除了具備臨時(EPHEMERAL)節點的特性之外,子節點的名稱還具有順序性。
你在使用的ZooKeeper 的時候,會發現 CreateMode
類中實際有 7種 znode 類型 ,但是用的最多的還是上面介紹的 4 種。
a.創建持久化節點
你可以通過下面兩種方式創建持久化的節點。
//注意:下面的代碼會報錯,下文說了具體原因
zkClient.create().forPath("/node1/00001");
zkClient.create().withMode(CreateMode.PERSISTENT).forPath("/node1/00002");
但是,你運行上面的代碼會報錯,這是因為的父節點node1
還未創建。
你可以先創建父節點 node1
,然后再執行上面的代碼就不會報錯了。
zkClient.create().forPath("/node1");
更推薦的方式是通過下面這行代碼, creatingParentsIfNeeded()
可以保證父節點不存在的時候自動創建父節點,這是非常有用的。
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/node1/00001");
b.創建臨時節點
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/node1/00001");
c.創建節點並指定數據內容
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/node1/00001","java".getBytes());
zkClient.getData().forPath("/node1/00001");//獲取節點的數據內容,獲取到的是 byte數組
d.檢測節點是否創建成功
zkClient.checkExists().forPath("/node1/00001");//不為null的話,說明節點創建成功
3.2.2. 刪除節點
a.刪除一個子節點
zkClient.delete().forPath("/node1/00001");
b.刪除一個節點以及其下的所有子節點
zkClient.delete().deletingChildrenIfNeeded().forPath("/node1");
3.2.3. 獲取/更新節點數據內容
zkClient.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/node1/00001","java".getBytes());
zkClient.getData().forPath("/node1/00001");//獲取節點的數據內容
zkClient.setData().forPath("/node1/00001","c++".getBytes());//更新節點數據內容
3.2.4. 獲取某個節點的所有子節點路徑
List<String> childrenPaths = zkClient.getChildren().forPath("/node1");
作者:Snailclimb
鏈接:【實戰】ZooKeeper 實戰
來源:github