Linux系統下zookeeper客戶端命令使用


1. 啟動客戶端

[admin@yrjk bin]$ ./zkCli.sh 
[zk: localhost:2181(CONNECTED) 0] 

2. 顯示所有操作命令

[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
    stat path [watch]
    set path data [version]
    ls path [watch]
    delquota [-n|-b] path
    ls2 path [watch]
    setAcl path acl
    setquota -n|-b val path
    history 
    redo cmdno
    printwatches on|off
    delete path [version]
    sync path
    listquota path
    rmr path
    get path [watch]
    create [-s] [-e] path data acl
    addauth scheme auth
    quit 
    getAcl path
    close 
    connect host:port
[zk: localhost:2181(CONNECTED) 1] 

3. 查看節點

[zk: localhost:2181(CONNECTED) 1] ls /      # ls命令用於查看節點,類似於Linux中的查看目錄
[zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls2 /     # ls2命令用於查看節點以及該節點狀態的詳細信息
[zookeeper]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 3] 

節點狀態的屬性描述如下:

[zk: localhost:2181(CONNECTED) 3] create /name Richard
Created /name
[zk: localhost:2181(CONNECTED) 4] stat /name     # stat命令用於查看節點狀態的詳細信息
cZxid = 0x6
ctime = Sun Dec 15 13:25:02 CST 2019
mZxid = 0x6
mtime = Sun Dec 15 13:25:02 CST 2019
pZxid = 0x6
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
[zk: localhost:2181(CONNECTED) 5] get /name      # get命令用於查看節點的數據以及節點狀態的詳細信息
Richard
cZxid = 0x6
ctime = Sun Dec 15 13:25:02 CST 2019
mZxid = 0x6
mtime = Sun Dec 15 13:25:02 CST 2019
pZxid = 0x6
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
[zk: localhost:2181(CONNECTED) 6]

4. 節點創建

znode一共有4種類型:持久的(persistent)、臨時的(ephemeral)、持久有序的(persistent_sequential)和臨時有序的(ephemeral_sequential)。

在節點創建之前,需要了解一下zk中session的特性:

  • 客戶端與服務端之間的連接存在會話
  • 每個會話都可以設置一個超時時間
  • 心跳結束,session則過期
  • session過期,則臨時節點znode會被拋棄
  • 心跳機制:客戶端向服務端的ping包請求
[zk: localhost:2181(CONNECTED) 2] create /name Richard
Created /name
[zk: localhost:2181(CONNECTED) 3] ls /
[name, zookeeper]
[zk: localhost:2181(CONNECTED) 4] get /name
Richard
cZxid = 0xe
ctime = Sun Dec 15 13:53:22 CST 2019
mZxid = 0xe
mtime = Sun Dec 15 13:53:22 CST 2019
pZxid = 0xe
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0
[zk: localhost:2181(CONNECTED) 5] 

這種創建方式創建出來的節點是持久化的,也就是持久節點(PERSISTENT)。所謂持久節點,是指在節點創建后,就一直存在,直到有刪除操作來主動清除這個節點——不會因為創建該節點的客戶端會話失效而消失。除了持久節點之外,我們還可以創建臨時節點(EPHEMERAL),那么我們來看看如何創建臨時節點:

[zk: localhost:2181(CONNECTED) 5] create -e /name/tmp Rachel 
Created /name/tmp      # -e 指定創建臨時節點
[zk: localhost:2181(CONNECTED) 6] get /name
Richard
cZxid = 0xe
ctime = Sun Dec 15 13:53:22 CST 2019
mZxid = 0xe
mtime = Sun Dec 15 13:53:22 CST 2019
pZxid = 0xf
cversion = 1   #由於在/name下創建了一個子節點,所以 cversion 的值就會進行累加
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0    #表示持久節點
dataLength = 7
numChildren = 1
[zk: localhost:2181(CONNECTED) 7] get /name/tmp
Rachel
cZxid = 0xf
ctime = Sun Dec 15 13:56:09 CST 2019
mZxid = 0xf
mtime = Sun Dec 15 13:56:09 CST 2019
pZxid = 0xf
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x100000be9f80004   #表示臨時節點
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 8] 

和持久節點不同的是,臨時節點的生命周期和客戶端會話綁定。也就是說,如果客戶端會話失效,那么這個節點就會自動被清除掉。注意,這里提到的是會話失效,而非連接斷開,當然連接斷開也會導致會話失效,但是並不是主要原因。另外,在臨時節點下面不能創建子節點。我們上面提到了,心跳結束,session就會過期,而session過期,則臨時節點znode就會被拋棄。那么我們來斷開與服務端的連接,看看臨時節點是否會被清除:

[zk: localhost:2181(CONNECTED) 8] ls /name
[tmp]
[zk: localhost:2181(CONNECTED) 9] quit   
Quitting...
2019-12-15 14:00:44,326 [myid:] - INFO  [main:ZooKeeper@687] - Session: 0x100000be9f80004 closed
2019-12-15 14:00:44,328 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@520] - EventThread shut down for session: 0x100000be9f80004
[admin@yrjk bin]$ ./zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /name    #重連之后,臨時節點被清除
[]
[zk: localhost:2181(CONNECTED) 1] 

以上我們演示了持久節點和臨時節點的創建,下面我們來看一下持久順序節點(PERSISTENT_SEQUENTIAL)的創建:

[zk: localhost:2181(CONNECTED) 3] create -s /name/seq num   #-s指定創建持久順序節點
Created /name/seq0000000001         # 會自動為給定節點名加上一個數字后綴
[zk: localhost:2181(CONNECTED) 4] ls /name 
[seq0000000001]
[zk: localhost:2181(CONNECTED) 5] create -s /name/seq num
Created /name/seq0000000002         # 再次創建節點數字就會遞增
[zk: localhost:2181(CONNECTED) 6] ls /name               
[seq0000000001, seq0000000002]
[zk: localhost:2181(CONNECTED) 7] create -s /name/otherseq num
Created /name/otherseq0000000003    # 創建前綴不同的節點,數字也會遞增
[zk: localhost:2181(CONNECTED) 8] ls /name                    
[otherseq0000000003, seq0000000001, seq0000000002]
[zk: localhost:2181(CONNECTED) 9] 

這類節點的基本特性和持久節點類型是一致的。額外的特性是,在ZK中,每個父節點會為他的第一級子節點維護一份時序,會記錄每個子節點創建的先后順序。基於這個特性,在創建子節點的時候,可以設置這個屬性,那么在創建節點過程中,ZK會自動為給定節點名加上一個數字后綴,作為新的節點名。這個數字后綴的范圍是整型的最大值。

當 -s 與 -e 選項同時使用就是創建臨時順序節點(EPHEMERAL_SEQUENTIAL) ,此節點是屬於臨時節點,不過帶有順序,和臨時節點一樣,當session過期節點就會消失,而客戶端會話連接結束也會導致session過期,所以同樣的該節點也會消失,這種類型的節點一般用於實現分布式鎖。以下演示一下臨時順序節點的創建方式:

[zk: localhost:2181(CONNECTED) 9] create /address Beijing   #創建一個持久節點
Created /address
[zk: localhost:2181(CONNECTED) 10] create -s -e /address/road Changan   #在持久節點下,創建臨時順序節點
Created /address/road0000000000
[zk: localhost:2181(CONNECTED) 11] create -s -e /address/road Changan
Created /address/road0000000001
[zk: localhost:2181(CONNECTED) 12] create -s -e /address/street Changan
Created /address/street0000000002
[zk: localhost:2181(CONNECTED) 13] ls /address
[road0000000000, road0000000001, street0000000002]
[zk: localhost:2181(CONNECTED) 14] quit
Quitting...
2019-12-15 14:15:09,721 [myid:] - INFO  [main:ZooKeeper@687] - Session: 0x100000be9f80005 closed
2019-12-15 14:15:09,723 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@520] - EventThread shut down for session: 0x100000be9f80005
[admin@yrjk bin]$ ./zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /address 
[]

5. 節點修改

使用set命令對某個節點進行修改:

[zk: localhost:2181(CONNECTED) 6] get /name
Richard
cZxid = 0xe
ctime = Sun Dec 15 13:53:22 CST 2019
mZxid = 0xe
mtime = Sun Dec 15 13:53:22 CST 2019
pZxid = 0x14
cversion = 5
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 3
[zk: localhost:2181(CONNECTED) 7] set /name David   #修改/name節點的數據
cZxid = 0xe
ctime = Sun Dec 15 13:53:22 CST 2019
mZxid = 0x1b
mtime = Sun Dec 15 14:19:21 CST 2019
pZxid = 0x14
cversion = 5
dataVersion = 1     # 此時數據版本就會遞增為1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 3
[zk: localhost:2181(CONNECTED) 8] get /name      
David
cZxid = 0xe
ctime = Sun Dec 15 13:53:22 CST 2019
mZxid = 0x1b
mtime = Sun Dec 15 14:19:21 CST 2019
pZxid = 0x14
cversion = 5
dataVersion = 1     # 數據版本遞增為1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 3
[zk: localhost:2181(CONNECTED) 9] 

我們可以利用數據版本 dataVersion 來達到一個樂觀鎖的效果,所以每次我們修改節點數據的時候,應該加上這個 dataVersion 的值去進行修改,以免在並發的時候導致數據不一致:

[zk: localhost:2181(CONNECTED) 9] set /name Sam 1   #指定版本去修改
cZxid = 0xe
ctime = Sun Dec 15 13:53:22 CST 2019
mZxid = 0x1c
mtime = Sun Dec 15 14:22:33 CST 2019
pZxid = 0x14
cversion = 5
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 3
[zk: localhost:2181(CONNECTED) 10] set /name Sam1 1   # 如果再次使用版本1去修改數據,就會報錯
version No is not valid : /name
[zk: localhost:2181(CONNECTED) 11] 

6. 節點刪除

使用delete命令可以對某個節點進行刪除:

[zk: localhost:2181(CONNECTED) 12] ls /name
[otherseq0000000003, seq0000000001, seq0000000002]
[zk: localhost:2181(CONNECTED) 13] delete /name/seq0000000001    #刪除節點
[zk: localhost:2181(CONNECTED) 14] ls /name                  
[otherseq0000000003, seq0000000002]
[zk: localhost:2181(CONNECTED) 15] delete /name/seq0000000002 0    #指定版本號刪除節點
[zk: localhost:2181(CONNECTED) 16] ls /name                  
[otherseq0000000003]

使用rmr命令可以對節點進行遞歸刪除:

[zk: localhost:2181(CONNECTED) 16] ls /     
[name, address, zookeeper]
[zk: localhost:2181(CONNECTED) 17] rmr /name  #遞歸刪除節點
[zk: localhost:2181(CONNECTED) 18] ls /     
[address, zookeeper]
[zk: localhost:2181(CONNECTED) 19] 

7. watcher機制

watcher是zk中比較重要的特性,定義如下:

  • 針對每個節點的操作,都會有一個監督者 -> watcher
  • 當監控的某個對象(znode)發生了變化,則觸發watcher事件
  • 簡單來說,watcher類似於sql中的觸發器
  • zk中的watcher是一次性的,觸發后立即銷毀
  • 父節點,子節點 的增刪改都能夠觸發其watcher
  • 針對不同類型的操作,觸發的watcher事件也不同:
    • (子)節點創建事件
    • (子)節點刪除事件
    • (子)節點數據變化事件

7.1 父節點watcher事件

watcher命令行學習:

  • 通過get path [watcher] 可以設置watcher,其他的諸如stat、ls、ls2命令也可以設置watcher
  • 父節點 增 刪 改 操作觸發watcher
  • 子節點 增 刪 改 操作觸發watcher

watcher事件類型-父節點:

  • 創建父節點觸發 NodeCreated 事件
  • 修改父節點數據觸發 NodeDataChanged 事件
  • 刪除父節點觸發 NodeDeleted 事件

創建父節點觸發 NodeCreated 事件,示例:

[zk: localhost:2181(CONNECTED) 19] stat /testWatch watch  # 在節點創建之前,我們可以通過 stat 命令去設置watcher
Node does not exist: /testWatch
[zk: localhost:2181(CONNECTED) 20] create /testWatch test-data  # 創建父節點

WATCHER::

WatchedEvent state:SyncConnected type:NodeCreated path:/testWatch  # 觸發 NodeCreated 事件
Created /testWatch
[zk: localhost:2181(CONNECTED) 21]

修改父節點數據觸發 NodeDataChanged 事件,示例:

[zk: localhost:2181(CONNECTED) 21] get /testWatch watch  # 因為zk事件是一次性的,所以我們還需要通過 get 命令設置 watcher
test-data
cZxid = 0x19
ctime = Sun Apr 22 23:37:08 CST 2018
mZxid = 0x19
mtime = Sun Apr 22 23:37:08 CST 2018
pZxid = 0x19
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0
[zk: localhost:2181(CONNECTED) 22] set /testWatch new-data  # 修改父節點數據

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/testWatch  # 觸發 NodeDataChanged 事件
cZxid = 0x19
ctime = Sun Apr 22 23:37:08 CST 2018
mZxid = 0x1a
mtime = Sun Apr 22 23:40:32 CST 2018
pZxid = 0x19
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: localhost:2181(CONNECTED) 23] 

刪除父節點觸發 NodeDeleted 事件,示例:

[zk: localhost:2181(CONNECTED) 23] ls /testWatch watch  # 通過 ls 命令來設置 watcher
[]
[zk: localhost:2181(CONNECTED) 24] delete /testWatch  # 刪除父節點

WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/testWatch  # 觸發 NodeDeleted 事件
[zk: localhost:2181(CONNECTED) 25]

7.2 子節點watcher事件

watcher事件類型-子節點:

  • 使用 ls 命令為父節點設置watcher,創建子節點時就會觸發 NodeChildrenChanged 事件
  • 使用 ls 命令為父節點設置watcher,刪除子節點時也會觸發 NodeChildrenChanged 事件
  • 使用 ls 命令為父節點設置watcher,修改子節點數據時不會觸發任何事件
  • 使用 get 命令為子節點設置watcher,修改子節點數據時會觸發 NodeDataChanged 事件

使用 ls 命令為父節點設置watcher,創建子節點時就會觸發 NodeChildrenChanged 事件,示例:

[zk: localhost:2181(CONNECTED) 29] create /testWatch test-data  # 創建父節點
Created /testWatch
[zk: localhost:2181(CONNECTED) 30] ls /testWatch watch  # 使用 ls 命令為父節點設置watcher
[]
[zk: localhost:2181(CONNECTED) 31] create /testWatch/testChildren children-data  # 創建子節點

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/testWatch  # 觸發 NodeChildrenChanged 事件
Created /testWatch/testChildren
[zk: localhost:2181(CONNECTED) 32] 

使用 ls 命令為父節點設置watcher,刪除子節點時也會觸發 NodeChildrenChanged 事件,示例:

[zk: localhost:2181(CONNECTED) 32] ls /testWatch watch   # 使用 ls 命令為父節點設置watcher
[testChildren]
[zk: localhost:2181(CONNECTED) 33] delete /testWatch/testChildren   # 刪除子節點          

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/testWatch   # 觸發 NodeChildrenChanged 事件
[zk: localhost:2181(CONNECTED) 34] 

簡單說明一下為什么創建和刪除子節點都是觸發 NodeChildrenChanged 事件,這是因為子節點都是掛在父節點之下,而我們是給父節點設置的 watcher,不是給子節點設置 watcher ,不管子節點是刪除還是創建,都是一個改變的過程,所以都是觸發同一個事件。

使用 ls 命令為父節點設置watcher,修改子節點數據時不會觸發任何事件,示例:

[zk: localhost:2181(CONNECTED) 35] create /testWatch/testChildren children-data  # 創建子節點
[zk: localhost:2181(CONNECTED) 36] ls /testWatch watch   # 使用 ls 命令為父節點設置watcher        
[testChildren]
[zk: localhost:2181(CONNECTED) 37] set /testWatch/testChildren new-children-data  # 修改子節點數據時不會觸發任何事件
cZxid = 0x1f
ctime = Sun Apr 22 23:58:44 CST 2018
mZxid = 0x20
mtime = Sun Apr 22 23:59:24 CST 2018
pZxid = 0x1f
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 17
numChildren = 0
[zk: localhost:2181(CONNECTED) 38] 

不會觸發事件是因為這個watcher是設置在父節點上的,所以修改子節點數據時不會觸發父節點所設置的watcher事件。

使用 get 命令為子節點設置watcher,修改子節點數據時會觸發 NodeDataChanged 事件,示例:

[zk: localhost:2181(CONNECTED) 40] get /testWatch/testChildren watch  # 使用 get 命令為子節點設置watcher
new-children-data
cZxid = 0x1f
ctime = Sun Apr 22 23:58:44 CST 2018
mZxid = 0x21
mtime = Mon Apr 23 00:01:41 CST 2018
pZxid = 0x1f
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 17
numChildren = 0
[zk: localhost:2181(CONNECTED) 41] set /testWatch/testChildren new-children-data2  # 修改子節點數據

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/testWatch/testChildren   # 觸發 NodeDataChanged 事件
cZxid = 0x1f
ctime = Sun Apr 22 23:58:44 CST 2018
mZxid = 0x22
mtime = Mon Apr 23 00:02:11 CST 2018
pZxid = 0x1f
cversion = 0
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 18
numChildren = 0
[zk: localhost:2181(CONNECTED) 42] 

 

參考:ZooKeeper:分布式過程協同技術詳解

https://blog.51cto.com/zero01/2106494


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM