ZooKeeper之CLI

ZooKeeper CLI(客戶端)

ZooKeeper命令行界面(CLI)用於與ZooKeeper服務端進行交互,以進行開發。它有助於調試和解決不同的選項。
要執行ZooKeeper CLI操作,首先打開ZooKeeper服務器。

進入ZooKeeper的bin目錄執行以下命令

./zkServer.sh start

啓動成功

ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

然後打開ZooKeeper客戶端

./zkCli.sh

啓動成功

Connecting to localhost:2181
2019-08-24 17:21:13,419 [myid:] - INFO  [main:Environment@100] - Client environment:zookeeper.version=3.4.9-1757313, built on 08/23/2016 06:50 GMT
2019-08-24 17:21:13,422 [myid:] - INFO  [main:Environment@100] - Client environment:host.name=bogon
2019-08-24 17:21:13,422 [myid:] - INFO  [main:Environment@100] - Client environment:java.version=1.8.0_181
2019-08-24 17:21:13,424 [myid:] - INFO  [main:Environment@100] - Client environment:java.vendor=Oracle Corporation
2019-08-24 17:21:13,424 [myid:] - INFO  [main:Environment@100] - Client environment:java.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64/jre
2019-08-24 17:21:13,424 [myid:] - INFO  [main:Environment@100] - Client environment:java.class.path=/opt/zookeeper-3.4.9/bin/../build/classes:/opt/zookeeper-3.4.9/bin/../build/lib/*.jar:/opt/zookeeper-3.4.9/bin/../lib/slf4j-log4j12-1.6.1.jar:/opt/zookeeper-3.4.9/bin/../lib/slf4j-api-1.6.1.jar:/opt/zookeeper-3.4.9/bin/../lib/netty-3.10.5.Final.jar:/opt/zookeeper-3.4.9/bin/../lib/log4j-1.2.16.jar:/opt/zookeeper-3.4.9/bin/../lib/jline-0.9.94.jar:/opt/zookeeper-3.4.9/bin/../zookeeper-3.4.9.jar:/opt/zookeeper-3.4.9/bin/../src/java/lib/*.jar:/opt/zookeeper-3.4.9/bin/../conf:
2019-08-24 17:21:13,424 [myid:] - INFO  [main:Environment@100] - Client environment:java.library.path=/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2019-08-24 17:21:13,424 [myid:] - INFO  [main:Environment@100] - Client environment:java.io.tmpdir=/tmp
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:java.compiler=<NA>
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:os.name=Linux
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:os.arch=amd64
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:os.version=3.10.0-957.el7.x86_64
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:user.name=root
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:user.home=/root
2019-08-24 17:21:13,425 [myid:] - INFO  [main:Environment@100] - Client environment:user.dir=/opt/zookeeper-3.4.9/bin
2019-08-24 17:21:13,426 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@7aec35a
2019-08-24 17:21:13,460 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error)
Welcome to ZooKeeper!
JLine support is enabled
2019-08-24 17:21:13,607 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session
2019-08-24 17:21:13,639 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x16cc029862a0005, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null

一旦ZooKeeper客戶端啓動成功,我們就可以和ZooKeeper服務端進行交互。

輸入help命令(其實輸入任何 zkCli 不能識別的命令,都會列出所有的命令),查看可用的命令:

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

現在讓我們用一個例子逐個瞭解上面的命令

創建節點 create

語法

create [-s] [-e] path data acl

注意:如果該節點不需要存儲任何數據則用''字符串表示,不可忽略,否則會報錯。

-s 創建有序節點

順序節點可以是持久的或臨時的。當一個新的節點被創建爲一個順序節點時,ZooKeeper通過將10位的序列號附加到原始名稱來設置節點的路徑

例如,如果將具有路徑 /myapp 的節點創建爲順序節點,則ZooKeeper會將路徑更改爲/myapp0000000001 ,並將下一個序列號設置爲0000000002。如果兩個順序節點是同時創建的,那麼ZooKeeper不會對每個節點使用相同的數字。順序節點在鎖定和同步中起重要作用

這個序號的計數器是由這些排序節點的父節點來維護的。

-e 創建臨時節點

客戶端活躍時,臨時節點就是有效的。當客戶端與ZooKeeper集合斷開連接時,臨時節點會自動刪除。因此,只有臨時節點不允許有子節點。如果臨時節點被刪除,則下一個合適的節點將填充其位置。臨時節點在leader選舉中起着重要作用。

acl 我們單獨在ZooKeeper之ACL做介紹

使用方法:

創建普通節點

create /mynode monkey

結果:

Created /mynode

創建子節點

/mynode節點下添加一個名爲/subnode的子節點

create /mynode/subnode ''

結果:

Created /mynode/subnode

如果父節點不存在,則會先創建父節點後再創建子節點。

注意:臨時節點不能擁有子節點。

創建有序節點

create -s /mynode ''
create -s /mynode ''

結果:

Created /mynode0000000003
Created /mynode0000000004

創建臨時節點

create -e /temp ''

結果:

Created /temp

關閉當前會話,然後重新打開它,發現/tmep節點已經被刪除了。

創建臨時有序節點

create -s -e /mynode ''

結果:

Created /mynode0000000006

關閉當前會話,然後重新打開它,發現/mynode0000000006節點已經被刪除了。

列出znode的子節點 ls or ls2

語法

ls path [watch]

ls命令類似於Linux中的dir

ls2 path [watch]

ls2命令來查看當前節點的所有子節點並能看到更新次數等數據,與ls不同的是它可以當前節點的stat(狀態)。

watch 添加一個監視器

[watch]添加一個watch(監視器)如果該節點發生變化,watch 可以使客戶端得到通知。watch 只能被觸發一次。如果要一直獲得znode的創建和刪除的通知,那麼就需要不斷的在znode上開啓觀察模式。

如果在該 path 下創建或刪除子節點,會產生 NodeChildrenChanged 事件;如果刪除自身節點則會產生 NodeDeleted 事件。

使用方法:

ls列出根節點下的所有子節點

ls /

結果:

[mynode0000000006, mynode, zookeeper, mynode0000000003]

ls2列出根節點

ls2 /

結果:

[mynode0000000006, mynode, zookeeper, mynode0000000003]
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 HKT 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 HKT 1970
pZxid = 0x2c
cversion = 10
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 4

列出子節點

ls /mynode

結果:

[subnode]

使用watch

我們在根節點創建一個名爲awatch

ls / a  

然後再根節點下添加子節點

create /mynode2 hello

就會觸發該watch

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/
Created /mynode2

注意:在其他節點下創建子節點,不會觸發該watch

從上面的操作可以看到,在根節點添加了 /mynode2 節點之後,觸發了 watchWatchedEvent的類型是 NodeChildrenChanged

獲取節點信息 get

語法

get path [watch]

watch 添加一個監視器

[watch]添加一個watch(監視器)如果該節點發生變化,watch 可以使客戶端得到通知。watch 只能被觸發一次。如果要一直獲得znode的創建和刪除的通知,那麼就需要不斷的在znode上開啓觀察模式。

如果節點內容發生改變,會產生NodeDataChanged事件;如果刪除節點,會產生NodeDeleted事件。

獲取/mynode數據

get /mynode

結果

22
cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x3e
mtime = Sun Aug 25 14:27:54 HKT 2019
pZxid = 0x3d
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0

每一個對znode樹的更新操作,都會被賦予一個全局唯一的ID,我們稱之爲zxid(Zookeeper Transaction ID)。更新操作的ID按照發生的時間順序升序排序。

Znode(節點)的stat結構中的字段顯示如下,各自的含義如下:
  • cZxid - 創建該 znodezxid
  • ctime - 創建該 znode 的時間。
  • mZxid - 這是最後修改znode更改的事務ID。
  • mtime - 最後一次修改該 znode 的時間。
  • pZxid - 這是用於添加或刪除子節點的znode更改的事務ID。
  • cversion - 該znode的子節點的版本。
  • dataVersion - znode內容的版本,每次修改內容,版本都會增加。
  • aclVersion - znodeACL的版本。
  • ephemeralOwner - 如果znode是ephemeral(臨時)節點,會列出該znode所在客戶端的 session id如果不是臨時節點,該值爲0
  • dataLength - 該znode存儲的數據長度。
  • numChildren - 該znode的子節點的個數。

使用watch

我們在/mynode節點創建一個名爲awatch

 get /mynode a

然後更改/mynode節點的數據

set /mynode 111    

就會觸發watch

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/mynode
cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x40
mtime = Sun Aug 25 17:08:53 HKT 2019
pZxid = 0x3f
cversion = 1
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1

從上面的操作可以看到,在修改/mynode的數據後,觸發了 watchWatchedEvent的類型是 NodeDataChanged

檢查狀態 stat

語法

stat path [watch]

watch 添加一個監視器

[watch]添加一個watch(監視器)如果該節點發生變化,watch 可以使客戶端得到通知。watch 只能被觸發一次。如果要一直獲得znode的創建和刪除的通知,那麼就需要不斷的在znode上開啓觀察模式。

如果節點內容發生改變,會產生NodeDataChanged事件;如果刪除節點,會產生NodeDeleted事件。

使用方法:

查看/mynode狀態

stat /mynode

結果:

cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x40
mtime = Sun Aug 25 17:08:53 HKT 2019
pZxid = 0x3f
cversion = 1
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1

get的區別是,不會列出節點的數據。

使用watch

我們在/mynode節點創建一個名爲awatch

stat /mynode a

然後更改/mynode節點的數據

set /mynode 222 

就會觸發watch

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/mynode
cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x41
mtime = Sun Aug 25 22:22:24 HKT 2019
pZxid = 0x3f
cversion = 1
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 1

從上面的操作可以看到,在修改/mynode的數據後,觸發了 watchWatchedEvent的類型是 NodeDataChanged

設置數據 set

語法

set path data [version]

修改已經存在的節點的數據。

version 指定版本號設置數據

[version]參數用於指定節點的數據版本,表名本次更新操作是針對指定的數據版本進行更新的。

如果指定znode版本號,需要與當前的版本號匹配。如果版本號不匹配,操作將會失敗。失敗的原因可能是在我們提交之前,該znode已經被修改過了,版本號發生了增量變化。如果不指定版本號,就是直接操作最新版本的 znode。

使用方法

修改/mynode的數據爲sayhello

set /mynode sayhello

結果:

cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x47
mtime = Sun Aug 25 23:18:27 HKT 2019
pZxid = 0x3f
cversion = 1
dataVersion = 5
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 1

我們通過get命令來查看/mynode

sayhello
cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x47
mtime = Sun Aug 25 23:18:27 HKT 2019
pZxid = 0x3f
cversion = 1
dataVersion = 5
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 1

可以看到sayhello已經被設置進去了。

我們來看看帶version參數的set

通過stat命令我們可以看到mynodedataVersion11

修改/mynode的數據爲sayhi,指定版本參數爲11

set /mynode sayhi 11

結果:

cZxid = 0x3d
ctime = Sun Aug 25 14:27:31 HKT 2019
mZxid = 0x5d
mtime = Mon Aug 26 11:19:56 HKT 2019
pZxid = 0x3f
cversion = 1
dataVersion = 12
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 1

可以看到,在修改節點值之後,mZxidmtimedataVersion 都發生了變化。

注意:如果version參數和/mynode節點的dataVersion所對應不上則會提示version No is not valid :/mynode(版本號無效:/mynode),並且修改數據失敗。

指定版本更新的意義何在?

通俗來講就是CAS(樂觀鎖),每次更新攜帶上次獲取到的vesion值進行更新。而如果在這段時間內,ZooKeeper服務器上該節點的數值恰好已經被其它客戶端更新了,那麼其節點的version值也一定會發生變化,一旦節點的version值發生了變化。我們的本次攜帶的vesion值就無法和服務端節點的vesion值匹配,於是便無法成功更新。 – 因此可以有效地避免一些分佈式更新的併發問題

刪除節點 rmr

語法

rmr path

使用方法:

刪除/mynode節點

rmr /mynode

使rmr命令刪除,不會返回任何內容。如果有子節點的時候,連帶子節點也一起刪除。

我們通過ls命令來查看/mynode節點是否被刪除了。

ls /

結果:

[zookeeper, mynode0000000003]

可以看到/mynode節點已經被刪除了。

刪除節點 delete

語法

delete path [version]

version 指定版本號刪除節點

[version]參數用於指定節點的數據版本,表名本次更新操作是針對指定的數據版本進行更新的。如果指定znode版本號,需要與當前的版本號匹配。如果版本號不匹配,操作將會失敗。失敗的原因可能是在我們提交之前,該znode已經被修改過了,版本號發生了增量變化。如果不指定版本號,就是直接操作最新版本的 znode。

使用方法:

我們先使用create創建一個名爲/mynode節點

create /mynode ''

結果:

Created /mynode

接着我們來使用delete命令刪除/mynode節點。

delete /mynode

使delete命令刪除,不會返回任何內容。如果有子節點的時候,將不能刪除。

我們通過ls命令來查看/mynode節點是否被刪除了。

ls /

結果:

[zookeeper, mynode0000000003]

可以看到/mynode節點已經被刪除了。

我們來看看帶version參數的delete

我們先使用create創建一個名爲/mynode節點

create /mynode ''

結果:

Created /mynode

通過stat命令我們可以看到mynodedataVersion0

刪除/mynode,指定版本參數爲0

delete /mynode 0

我們通過ls命令來查看/mynode節點是否被刪除了。

ls /

結果:

[zookeeper, mynode0000000003]

可以看到/mynode節點已經被刪除了。

注意:如果version參數和/mynode節點的dataVersion所對應不上則會提示version No is not valid :/mynode(版本號無效:/mynode),並且刪除失敗。

deletermr的區別
  1. delete只能刪除葉節點,也就是說帶有子節點的節點將刪除失敗,相反rmr可以刪除帶有子節點的節點。
  2. delete能帶version進行刪除,相反rmr不支持

其他指令

歷史記錄 history

語法

history 

使用方法:

列出最近的10條歷史記錄。

history 

結果:

14 - rmr /mynode
15 - ls /
16 - create /mynode ''
17 - delete /mynode
18 - ls /
19 - create /mynode ''
20 - stat /mynode
21 - delete /mynode 1
22 - delete /mynode 0
23 - help
24 - history

重複之前的命令 redo

語法

redo cmdno

使用方法:

根據 cmdno 重複之前的命令,cmdno 就是方括號裏面最後的數字,每次執行命令都會自增

[zk: localhost:2181(CONNECTED) 28] create /mynode ''
Created /mynode
[zk: localhost:2181(CONNECTED) 29] rmr /mynode
[zk: localhost:2181(CONNECTED) 30] redo 28
Created /mynode

是否輸出 watch 事件 printwatches on | off

語法

printwatches on|off

on 代表會輸出watch事件,off代表不會輸出watch事件

使用方法:

查看當前printwatches的值

printwatches

結果:

printwatches is on

我們在根節點創建一個名爲awatch

ls / a  

並刪除掉根節點中的其中一個子節點,觸發watch

rmr /mynode

結果:

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/

輸出了watch事件

我們將printwatches的值更改爲off

printwatches off

我們繼續在根節點創建一個名爲awatch

ls / a  

並在根節點中創建一個子節點,觸發watch

create /mynode ''

結果:

Created /mynode

並沒有輸出watch事件.

關閉連接 close

語法

close

使用方法:

關閉連接(會話)

close

結果:

2019-08-26 18:07:57,745 [myid:] - INFO  [main:ZooKeeper@684] - Session: 0x16cc029862a000d closed
[zk: localhost:2181(CLOSED) 39] 2019-08-26 18:07:57,748 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@519] - EventThread shut down for session: 0x16cc029862a000d

再次對節點操作時

ls /

結果:

Not connected

打開連接 connect

語法

connect host:port

指定 host:port 可以連接遠程的 zk 服務。缺省的時候,會連接本地的 2181 端口。

使用方法:

連接本地的ZooKeeper服務端

connect localhost:2181

結果:

2019-08-26 18:15:32,037 [myid:] - INFO  [main:ZooKeeper@438] - Initiating client connection, connectString=localhost:2181 sessionTimeout=30000 watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@73a8dfcc
[zk: localhost:2181(CONNECTING) 4] 2019-08-26 18:15:32,041 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1032] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
2019-08-26 18:15:32,043 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@876] - Socket connection established to localhost/127.0.0.1:2181, initiating session
2019-08-26 18:15:32,055 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x16cc029862a000f, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null

再次對節點操作時

ls /

結果:

[mynode, zookeeper, mynode0000000003]

連接成功!!!

如果是連接本地ZooKeeper服務端並端口號是2181。則可以省略host:port參數。

退出客戶端 quit

語法

quit

直接退出當前的 zkCli 命令行。

使用方法:

退出客戶端

[zk: localhost:2181(CONNECTED) 6] quit

結果:

[root@bogon bin]# 

強制同步 sync

語法

sync path

sync方法會強制客戶端所連接的服務器狀態與leader的狀態同步,這樣在讀取節點的值就是最新的值了。

使用方法:

同步/mynode節點

sync /mynode

結果:

 Sync returned 0

由於我這邊是單機架構所以returned0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章