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

Linux系统下zookeeper客户端命令使用的更多相关文章

  1. Linux系统下利用wget命令把整站下载做镜像网站

    Linux系统下利用wget命令把整站下载做镜像网站 2011-05-28 18:13:01 | 1次阅读 | 评论:0 条 | itokit  在linux下完整的用wget命令整站采集网站做镜像 ...

  2. Linux系统下的shutdown命令用于安全的关闭/重启计算机

    Linux系统下的shutdown命令用于安全的关闭/重启计算机,它不仅可以方便的实现定时关机,还可以由用户决定关机时的相关参数.在执行shutdown命令时,系统会给每个终端(用户)发送一条屏显,提 ...

  3. 【转载】在Linux系统下用dd命令制作ISO镜像U盘启动盘

    #### 将U盘插入USB接口 #umount /dev/sdb* #dd if=/iso存放路径/XXX.iso of=/dev/sdb bs=1M ##### [转载]在Linux系统下用dd命令 ...

  4. 【Linux】---Linux系统下各种常用命令总结

    在Linux系统下,“万物皆文件”,之所以强调在强调这个概念,是因为很多人已经习惯了win系统下找找点点得那种方式和思维,因此总是会觉得linux系统下很多指令既复杂又难记.其实都是一样得东西,只是w ...

  5. 在Linux系统下用dd命令制作ISO镜像U盘启动盘

    http://os.51cto.com/art/201510/494762.htm 首先在 Linux 系统中打开终端,确认 U 盘路径: sudo fdisk -l 使用 dd 命令,格式如下: s ...

  6. 电源管理ACPI、及APM、GNU/Linux系统下的相应命令使用

    /*********************************************************************  * Author  : Samson  * Date   ...

  7. 云服务器 ECS Linux 系统下使用 dig 命令查询域名解析

    云服务器 ECS Linux 系统可以使用通常自带的 dig 命令来查询域名解析情况.本文对此进行简要说明. 查询域名 A 记录 命令格式: dig <域名> 比如,查询域名 www.al ...

  8. centos 64位linux系统下安装appt命令

    首先,安装apktool包 1. wget http://android-apktool.googlecode.com/files/apktool-install-linux-r04-brut1.ta ...

  9. Linux系统下zookeeper的安装和配置

    ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功 ...

随机推荐

  1. android中的webview白屏问题

     最近在使用WebView的时候,发现了一个小问题,很多初学者应该会注意不到! WebView的layerType属性有三个值. 1.none,默认值, 2.software,软件加速, 3.hard ...

  2. SpringBoot 通过配置禁用swagger

    转自:https://blog.csdn.net/weixin_37264997/article/details/82762050 一.序言 在生产环境下,我们需要关闭swagger配置,避免暴露接口 ...

  3. 连接mysql报"ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this MySQL server"

    最近在服务器上部署好的应用突然间连接不上mysql数据库,报错“ERROR 1130: Host xxx.xxx.xxx.xxx is not allowed to connect to this M ...

  4. 不知道密码情况下 进行docker数据库可视化连接

    1. 通过命令 docker inpect mysql容器id ,查询mysql容器的密码和绑定的端口号 2.通过vscode插件或者navicat等可视化工具,进行连接即可. 有问题请进群联系我,或 ...

  5. Golang: 解析JSON数据之一

    JSON 作为目前最流行的数据传输格式, 相信每个程序员都跟它打过交道吧.使用 Go 语言时,也不可避免的要操作 JSON 数据,令人惊喜的是,Go 内置了序列化和反序列化 JSON 的功能,今天就来 ...

  6. python生成图片二维码(利用pillow)

    首先 pip install pillow 然后 from PIL import Image from PIL import ImageDraw from PIL import ImageFont i ...

  7. NLP文本分类方法汇总

    模型: FastText TextCNN TextRNN RCNN 分层注意网络(Hierarchical Attention Network) 具有注意的seq2seq模型(seq2seq with ...

  8. httprunner学习9-完整的用例结构(yaml&json)

    前言 前面几篇零散的学了一些httprunner的知识点,那么一个完整的 YAML/JSON 用例文件包含哪些关键字呢? 测试用例结构 在 HttpRunner 中,测试用例组织主要基于三个概念: 测 ...

  9. mysql-xtrabackup备份恢复

    1.xtrabackup的安装 8.0版本-支持mysql8 wget https://www.percona.com/downloads/Percona-XtraBackup-LATEST/Perc ...

  10. 2019牛客暑期多校训练营(第六场) H:Train Driver (最短路+概率)

    题意:给定无向图,Alice在A集合选一个点,Bob在B集合选一个点,CXK在全集里选择一个点. 然后问“三人到某一点集合打篮球的最小距离”的期望. 思路:做过一个裸题,就是给定三人位置,问去哪里集合 ...