1. ZK節點的組織
zookeeper採用樹狀結構對數據進行存儲,整個數據存儲結構非常類似於linux的文件系統。如下圖所示,節點node_1的路徑是/node_1,節點node_1_1的路徑是/node_1/node_1_1。zookeeper就是通過對這些節點進行創建、刪除、修改、讀取等操作來完成系統功能的。
2. ZK節點的數據結構
cZxid = 0x300000002
ctime = Thu Dec 08 23:29:53 CST 2011
mZxid = 0xe00008bbf
mtime = Thu Jul 28 07:17:34 CST 2012
pZxid = 0x300000002
cversion = 0
dataVersion = 2164293
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 39
numChildren = 0
在zookeeper中,每次對數據節點的寫操作都是一個事務,每個事務都有一個唯一的事務id作爲這個事務的標識。
- cZxid就是創建這個節點的事務id。每個Zookeeper狀態的變化都以zxid(事務ID)的形式接收到標記。這個暴露了Zookeeper所有變化的總排序。每個變化都會有一個zxid,並且如果zxid1早於zxid2則zxid1一定小於zxid2。
- ctime是創建這個節點的時間。
- mZxid是最後更新該節點的事務id。
- mtime是節點被最後更新的時間。
- pZxid是節點的子節點列表被最後一次更新的事務id。子節點列表被更新只有兩種情況,分別是“增加子節點”和“刪除子節點”。修改子節點的數據內容不包括在內。
- cversion是當前節點的子節點的變更版本號。
- dataVersion當前節點存儲數據內容的變更版本號。
- aclVersion當前數據節點acl的變更版本號。上面3個版本號均可以用於實現樂觀鎖。
- ephemeralOwner爲創建該臨時節點的事務id。如果是持久節點,那麼該值固定爲0。
- dataLength表示當前節點存儲數據內容的長度。
- numChildren表示當前節點包含的子節點個數。
3. 節點的類型
Znode有四種類型,PERSISTENT(持久節點)、PERSISTENT_SEQUENTIAL(持久的連續節點)、EPHEMERAL(臨時節點)、EPHEMERAL_SEQUENTIAL(臨時的連續節點),Znode的類型在創建時確定並且之後不能再修改
3.1. 臨時節點
臨時節點的生命週期和客戶端會話綁定。也就是說,如果客戶端會話失效,那麼這個節點就會自動被清除掉。臨時節點不能有子節點
String root = "/ephemeral";
String createdPath = zk.create(root, root.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("createdPath = " + createdPath);
String path = "/ephemeral/test01" ;
createdPath = zk.create(path, path.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("createdPath = " + createdPath);
Thread.sleep(1000 * 20); // 等待20秒關閉ZooKeeper連接
zk.close(); // 關閉連接後創建的臨時節點將自動刪除
3.2. 持久節點
所謂持久節點,是指在節點創建後,就一直存在,直到有刪除操作來主動清除這個節點——不會因爲創建該節點的客戶端會話失效而消失。
String root = "/computer";
String createdPath = zk.create(root, root.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("createdPath = " + createdPath);
3.3. 臨時順序節點
臨時節點的生命週期和客戶端會話綁定。也就是說,如果客戶端會話失效,那麼這個節點就會自動被清除掉。注意創建的節點會自動加上編號。
String root = "/ephemeral";
String createdPath = zk.create(root, root.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("createdPath = " + createdPath);
String path = "/ephemeral/test01" ;
createdPath = zk.create(path, path.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("createdPath = " + createdPath);
Thread.sleep(1000 * 20); // 等待20秒關閉ZooKeeper連接
zk.close(); // 關閉連接後創建的臨時節點將自動刪除
3.4. 持久順序節點
這類節點的基本特性和持久節點類型是一致的。額外的特性是,在ZooKeeper中,每個父節點會爲他的第一級子節點維護一份時序,會記錄每個子節點創建的先後順序。基於這個特性,在創建子節點的時候,可以設置這個屬性,那麼在創建節點過程中,ZooKeeper會自動爲給定節點名加上一個數字後綴,作爲新的節點名。這個數字後綴的範圍是整型的最大值。
String root = "/computer";
String createdPath = zk.create(root, root.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("createdPath = " + createdPath);
for (int i=0; i<5; i++) {
String path = "/computer/node";
String createdPath = zk.create(path, path.getBytes(),
Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
System.out.println("createdPath = " + createdPath);
}
zk.close();
4. 節點刪除的時機
兩個場景下會刪除:第一、用戶自己手動觸發;第二、session過期
通過下邊這兩個命令就可以把節點刪除
delete path [version] :加版本號則會選擇刪除選中版本的節點,不加則直接刪除節點。(有子節點無法刪除)
rmr path :此命令用於強制刪除當前節點以及子節點
對應的Java代碼:
//同步刪除節點
zk.delete("/testRoot/children", -1);
//異步刪除節點
zk.delete("/testRoot/children", -1, new AsyncCallback.VoidCallback() {
@Override
public void processResult(int rc, String path, Object ctx) {
System.out.println("rc====="+rc);
System.out.println("path======"+path);
System.out.println("ctc======"+path);
}
} , "回調值");
參考文章:
http://arganzheng.life/zookeeper-introduction.html
https://dawn-jt.github.io/2018/12/16/Zookeeper/Zookeeper%E6%89%AB%E7%9B%B2/
https://segmentfault.com/a/1190000012070655
https://www.hollischuang.com/archives/1280