ZooKeeper命令⾏操作
⾸先,进⼊到zookeeper的bin⽬录之后,通过zkClient进⼊zookeeper客户端命令⾏
1 2
| ./zkcli.sh 连接本地的zookeeper服务器 ./zkCli.sh -server ip:port(2181) 连接指定的服务器
|
连接成功之后,系统会输出Zookeeper的相关环境及配置信息等信息。输⼊help之后,屏幕会输出可⽤的Zookeeper命令,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| [zk: localhost:2181(CONNECTED) 3] 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命令,可以创建⼀个Zookeeper节点, 如
1
| create [-s][-e] path data
|
其中,-s或-e分别指定节点特性,顺序或临时节点,若不指定,则创建持久节点
创建顺序节点
使⽤命令创建zk-test顺序节点
1 2
| [zk: localhost:2181(CONNECTED) 4] create -s /zk-test 123 Created /zk-test0000000000
|
执⾏完后,就在根节点下创建了⼀个叫做/zk-test的节点,该节点内容就是123,同时可以看到创建的zk-test节点后⾯添加了⼀串数字以示区别
创建临时节点
使⽤命令创建zk-temp临时节
1 2 3 4
| [zk: localhost:2181(CONNECTED) 1] create -e /zk-temp 123 Created /zk-temp [zk: localhost:2181(CONNECTED) 2] ls / [zk-test0000000000, zookeeper, zk-temp]
|
临时节点在客户端会话结束后,就会⾃动删除,下⾯使⽤quit命令退出客户端
1 2
| [zk: localhost:2181(CONNECTED) 3] quit Quitting...
|
再次使⽤客户端连接服务端,并使⽤ls / 命令查看根⽬录下的节点
1 2
| [zk: localhost:2181(CONNECTED) 0] ls / [zk-test0000000000, zookeeper]
|
可以看到根⽬录下已经不存在zk-temp临时节点了
创建永久节点
使⽤命令创建zk-permanent永久节点 ,可以看到永久节点不同于顺序节点,不会⾃动在后⾯添加⼀串数字
1 2 3 4
| [zk: localhost:2181(CONNECTED) 1] create /zk-permanent 123 Created /zk-permanent [zk: localhost:2181(CONNECTED) 2] ls / [zk-permanent, zk-test0000000000, zookeeper]
|
读取节点
与读取相关的命令有 ls 命令和 get 命令,其中,path表示的是指定数据节点的节点路径
ls 命令可以列出Zookeeper指定节点下的所有⼦节点,但只能查看指定节点下的第⼀级的所有⼦节点: ls path
get 命令可以获取Zookeeper指定节点的数据内容和属性信息: get path
若获取根节点下⾯的所有⼦节点,使⽤ls / 命令即可
1 2
| [zk: localhost:2181(CONNECTED) 2] ls / [zk-permanent, zk-test0000000000, zookeeper]
|
若想获取/zk-permanent的数据内容和属性,可使⽤如下命令:get /zk-permanent
1 2 3 4 5 6 7 8 9 10 11 12 13
| [zk: localhost:2181(CONNECTED) 3] get /zk-permanent 123 cZxid = 0x300000008 ctime = Thu Jul 16 04:33:41 EDT 2020 mZxid = 0x300000008 mtime = Thu Jul 16 04:33:41 EDT 2020 pZxid = 0x300000008 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0
|
从上⾯的输出信息中,我们可以看到,第⼀⾏是节点/zk-permanent 的数据内容,其他⼏⾏则是创建该节点的事务ID(cZxid)、最后⼀次更新该节点的事务ID(mZxid)和最后⼀次更新该节点的时间(mtime)等属性信息
更新节点
使⽤set命令,可以更新指定节点的数据内容,⽤法如下
其中,data就是要更新的新内容,version表示数据版本,在zookeeper中,节点的数据是有版本概念的,这个参数⽤于指定本次更新操作是基于Znode的哪⼀个数据版本进⾏的,如可以使⽤如下命令,将/zk-permanent节点的数据更新为456
1 2 3 4 5 6 7 8 9 10 11 12
| [zk: localhost:2181(CONNECTED) 4] set /zk-permanent 456 cZxid = 0x300000008 ctime = Thu Jul 16 04:33:41 EDT 2020 mZxid = 0x300000009 mtime = Thu Jul 16 05:07:00 EDT 2020 pZxid = 0x300000008 cversion = 0 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 3 numChildren = 0
|
现在dataVersion已经变为1了,表示进⾏了更新
删除节点
使⽤delete命令可以删除Zookeeper上的指定节点,⽤法如下
其中version也是表示数据版本,使⽤delete /zk-permanent 命令即可删除/zk-permanent节点
1 2 3
| [zk: localhost:2181(CONNECTED) 8] delete /zk-permanent [zk: localhost:2181(CONNECTED) 9] ls / [zk-test0000000000, zookeeper]
|
可以看到,已经成功删除/zk-permanent节点。值得注意的是,若删除节点存在⼦节点,那么⽆法删除该节点,必须先删除⼦节点,再删除⽗节点
Zookeeper的Java开源客户端
ZkClient是Github上⼀个开源的zookeeper客户端,在Zookeeper原⽣API接⼝之上进⾏了包装,是⼀个更易⽤的Zookeeper客户端,同时,zkClient在内部还实现了诸如Session超时重连、Watcher反复注册等功能
接下来,还是从创建会话、创建节点、读取数据、更新数据、删除节点等⽅⾯来介绍如何使⽤zkClient这个zookeeper客户端
创建maven工程
- 添加依赖
在pom.xml⽂件中添加如下内容
1 2 3 4 5 6 7 8 9 10 11 12
| <dependencies> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.14</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.2</version> </dependency> </dependencies>
|
- 创建会话
使⽤ZkClient可以轻松的创建会话,连接到服务端。
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.hust.grid.leesf.zkclient.examples;
import org.I0Itec.zkclient.ZkClient;
public class CreateSession {
public static void main(String[] args) { ZkClient zkClient = new ZkClient("127.0.0.1:2181"); System.out.println("ZooKeeper session created."); } }
|
运⾏结果:ZooKeeper session created.
结果表明已经成功创建会话。
创建节点
ZkClient提供了递归创建节点的接⼝,即其帮助开发者先完成⽗节点的创建,再创建⼦节点
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.hust.grid.leesf.zkclient.examples;
import org.I0Itec.zkclient.ZkClient;
public class Create_Node_Sample { public static void main(String[] args) { ZkClient zkClient = new ZkClient("127.0.0.1:2181"); System.out.println("ZooKeeper session established."); zkClient.createPersistent("/lg-zkClient/lg-c1",true); System.out.println("success create znode."); } }
|
运⾏结果:success create znode.
结果表明已经成功创建了节点,值得注意的是,ZkClient通过设置createParents参数为true可以递归的先创建⽗节点,再创建⼦节点
删除节点
ZkClient提供了递归删除节点的接⼝,即其帮助开发者先删除所有⼦节点(存在),再删除⽗节点。
1 2 3 4 5 6 7 8 9 10 11 12
| package com.hust.grid.leesf.zkclient.examples;
import org.I0Itec.zkclient.ZkClient;
public class Del_Data_Sample { public static void main(String[] args) throws Exception { String path = "/lg-zkClient/lg-c1"; ZkClient zkClient = new ZkClient("127.0.0.1:2181", 5000); zkClient.deleteRecursive(path); System.out.println("success delete znode."); } }
|
运⾏结果: success delete znode.
结果表明ZkClient可直接删除带⼦节点的⽗节点,因为其底层先删除其所有⼦节点,然后再删除⽗节点
监听节点变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package com.hust.grid.leesf.zkclient.examples;
import org.I0Itec.zkclient.IZkChildListener; import org.I0Itec.zkclient.ZkClient; import org.apache.zookeeper.client.ZooKeeperSaslClient; import java.util.List;
public class Get_Child_Change { public static void main(String[] args) throws InterruptedException { final ZkClient zkClient = new ZkClient("linux121:2181"); zkClient.subscribeChildChanges("/lg-client", new IZkChildListener() { public void handleChildChange(String path, List<String> childs) throws Exception { System.out.println(path + " childs changes ,current childs " + childs); } });
zkClient.createPersistent("/lg-client"); Thread.sleep(1000); zkClient.createPersistent("/lg-client/c1"); Thread.sleep(1000); zkClient.delete("/lg-client/c1"); Thread.sleep(1000); zkClient.delete("/lg-client"); Thread.sleep(Integer.MAX_VALUE); } }
|
运⾏结果:
1 2 3 4
| /lg-zkClient 's child changed, currentChilds:[] /lg-zkClient 's child changed, currentChilds:[c1] /lg-zkClient 's child changed, currentChilds:[] /lg-zkClient 's child changed, currentChilds:null
|
结果表明:
监听节点数据变化(节点是否存在、更新、删除)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| package com.lagou.zk.demo;
import org.I0Itec.zkclient.IZkDataListener; import org.I0Itec.zkclient.ZkClient;
public class Get_Data_Change { public static void main(String[] args) throws InterruptedException { final ZkClient zkClient = new ZkClient("Linux121:2181"); zkClient.setZkSerializer(new ZkStrSerializer()); final boolean exists = zkClient.exists("/lg-client1"); if (!exists) { zkClient.createEphemeral("/lg-client1", "123"); } zkClient.subscribeDataChanges("/lg-client1", new IZkDataListener() { public void handleDataChange(String path, Object data) throws Exception { System.out.println(path + " data is changed ,new data " + data); } public void handleDataDeleted(String path) throws Exception { System.out.println(path + " is deleted!!"); } }); final Object o = zkClient.readData("/lg-client1"); System.out.println(o); zkClient.writeData("/lg-client1", "new data"); Thread.sleep(1000); zkClient.delete("/lg-client1"); Thread.sleep(Integer.MAX_VALUE); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.lagou.zk.demo;
import org.I0Itec.zkclient.exception.ZkMarshallingError; import org.I0Itec.zkclient.serialize.ZkSerializer;
public class ZkStrSerializer implements ZkSerializer { public byte[] serialize(Object o) throws ZkMarshallingError { return String.valueOf(o).getBytes(); } public Object deserialize(byte[] bytes) throws ZkMarshallingError { return new String(bytes); } }
|
运⾏结果:
1 2 3
| 123 /lg-client1 data is changed ,new data new data /lg-client1 is deleted!!
|
结果表明可以成功监听节点数据变化或删除事件。