浅谈zookeeper数据结构及实操
之前我们已经掌握了linux基础知识,vim快速入门,linux下的软件安装方法以及shell基础编程,理解了zookeeper的概念和zookeeper集群的搭建,现在我们要深入学习zookeeper,看看他的数据结构是怎样的,又应该怎样操作呢?
1. 命令行客户端
前置条件:每台服务器的zookeeper服务均开启且处于正常运行状态
我们以node1节点为例。
查看zookeeper里的bin文件夹,其中的zkCli.sh为命令行客户端
在zookeeper目录下连接客户端:
bin/zkCli.sh
连接成功的显示如下:
通过localhost:2181(CONNECTED) 0 可以看出当前连接的服务器是自己(node1)。
如果想连接到node2,则在命令行输入:(我没有配置主机名和ip的映射)
connect 192.168.159.130:2181
即可连接到node2。
我们想使用zookeeper的更多功能,可以help查看指令。
根据我们之前的zookeeper概念及架构分析,我们要清楚的是,zookeeper提供的服务只有两大类,一类是读写数据,另一类就是监听。如果这里不明白的可以看我的另一篇博客“从几个实例出发---理解zookeeper概念(架构分析)”,博客地址:
https://blog.csdn.net/qq_34478594/article/details/105271012
在使用zookeeper之前,我们首先需要了解zookeeper读写的数据长得神马样?不然我们就没法读写它。
2 zookeeper数据结构
2.1 zookeeper的数据结构特性
1.层次化的目录结构,命名符合常规文件系统规范。下两张图是我在网上找的两张数据结构图,不过已经足够反应zookeeper数据结构特性了。
2.每个节点在zookeeper中叫做znode,并且有唯一的路径标识。
3.节点znode可以包含数据和子节点(但是EPHEMERAL类型的节点不能有子节点)。
4.客户端应用可以在节点上设置监听器。
*** 实操***
查看根节点信息:
ls /
我们发现,根节点下有一个子节点zookeeper。它存放的是zookeeper自己的一些信息。现在我们来创建一个自己的工作节点。
create /app1 “this is app1 servers parent”
现在我们在ls一下根节点,发现多了app1节点。
ls /
我们看在app1里还能不能在创建呢?当然可以了。我们在app1下创建server01,存放一个ip为192.168.159.130的服务器并假设可以负载100。
create /app1/server01 “192.168.159.130,100”
我们ls一下app1的子节点。
ls /app1
也可以get到节点的数据,如现在要getserver01的数据
get /app1/server01
我们发现除了得到我们自己写入的数据内容外还有其他的东西,他们都是节点状态信息。
cZxid 表示节点创建时的事务id;
ctime 表示节点创建时间;
mZxid 表示节点最后一次被修改时的事务id;
mtime 表示节点最后一次被修改的时间;
pZxid 表示该节点的子节点列表最后一次被修改时的事务id。只有子节点列表变更时才会更新pZxid,子节点的内容变更则不会更新;
cversion 表示子节点的版本号;
dataVersion 表示内容的版本号;
aclVersion 表示权限版本号;
dataLength 表示数据长度;
numChildren 表示子节点数;
ephemeralOwner表示创建该临时节点时的会话sessionID,如果是持久性节点则值为0。(关于节点类型后面详细说)
2.2 节点类型
1.znode有两种类型:
短暂(ephemeral)节点 (断开连接时自己删除)
持久(persistent)节点 (断开连接不删除)
这两种类型的设置是很有必要的,对于zookeeper感知就是基于短暂节点的。如某台服务器断线,这时这台服务器的短暂节点就会被zookeeper删除,此时zookeeper父节点就会产生事件,因为它发现自己的子节点减少了,从而感知到服务器掉线,并将消息发送给其他服务器让其他服务器也收到某台服务器掉线的消息从而做出进一步的处理。
2.znode有四种形式的目录节点(默认是persistent)
PERSISTENT,
PERSISTENT_SEQUENTIAL(持久序列/test0000000019)
EPHEMERAL
EPHEMERAL_ SEQUENTIAL
3,创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护。
******实操******
接着上一节的实操,我们继续。
现在我们想创建一个短暂节点。我们注意help里给出的create指令
create [-s] [-e] path data cal
这里的可选项[-e]就是代表短暂节点,加上就表示创建一个短暂节点。
create -e /app-ephemeral “okk”
查看根节点里是否添加了该节点,发现已经有app-ephmeral
ls /
只要在客户端没有退出之前,app-ephemeral都可以工作,如我们现在get一下节点的内容
get /app-ephemeral
我们发现ephemeralOwner的值有内容了,因为它是短暂节点。
现在我们用quit指令退出客户端,再重新进入 /bin/zkCli.sh,此时我们再ls一下根节点,发现app-ephemeral节点被自动删除了,验证了上述的结论。
我们在观察help给出的create指令create [-s] [-e] path data cal
我们发现它还有一个可选项[-s],它表示创建的节点是否带序号 SEQUENTIAL,即对应了
PERSISTENT_SEQUENTIAL和EPHEMERAL_ SEQUENTIAL。
那么带序号是什么意思呢,我们试验一下,创建一个带序号的节点和一个不带序号的节点。
create /test 888
create /test/aa 999
create -s /test/bb 999
我们发现bb后面多了一串序号。且序号是自增的。这样可以确保我们创建的每一个节点都是唯一的,不会产生冲突。
也可以更新节点,我们观察节点更新后的节点状态信息变化。
get /app1
set /app1 uuuu
刚才的操作都是在同一个节点node1进行的。现在在node1节点做set更新,我们在node3节点里启动zookeeper客户端,在node3中get /app1,观察是不是app1在node3中能够秒更新。
node3 ../zookeeper-3.4.14->
bin/zkCli.sh
node1 ->
set /app1 doUpdate
node3 ->
get /app1
我们通过实验可以发现,数据同步的速度是实时刷新的。当集群的节点数增加到几十台时,可能就会发生延迟。
我们再来观察help提供的指令,关注 get path [watch]
我们发现我们get节点时还可以带有watch,即zookeeper的第二大功能:监听服务。我们通过实验来体验这个传说中的监听功能。
get /app1 watch
当数据发送变化时,客户端就可以收到监听通知。我们在node3中修改app1
node3 ->
set /app1 hhhhhhhh
我们在回到node1,发现有东西自动输出,
我们发现输出的就是app1发生修改的通知。这就是监听功能。
我们继续实验,我们继续在node3节点中修改app1.
node3 ->
set /app1 kkkk
我们回到node1,发现这次没有输出新内容。
我们得出结论在get /app1 watch时,我们是在获取数据的时候注册了一个监听,它检测的是当该节点数据是否发生改变,而且这个监听只生效一次。
如果我们想监听该节点的子节点变化,需要在获取子节点时增加监听
node1 ->
ls /app1 watch
我们在node3中对app1做创建子节点的操作
node3 ->
create /app1/kkk aaaaa
我们返回node1,发现自动输出了子节点改变的监听消息
上面介绍了两种监听:监听数据发生的变化和监听子节点的变化,这两种也是实际工程中最常用的。
这样我们就把zookeeper的两大核心功能:读写数据和监听谈了一遍,并且通过实际操作感受了一下。相信大家跟着一起做的话,不仅能了解zookeeper的数据结构,也能熟悉zookeeper的命令行操作!