1.ZooKeeper数据结构和实操「第二章 ZooKeeper使用」「架构之路ZooKeeper理论和实战」
在前面我们说过,ZooKeeper 是一个开源的分布式协调服务框架。它本质上是一个分布式的小文件存储系统,提供类似与文件系统目录树方式的数据存储,并且可以对树中的节点进行有效管理,从而用来维护和监控存储的数据的状态变化,通过监控这些数据状态的变化,实现基于数据的集群管理。
所以我们可以这么理解:ZooKeeper = 文件系统 + 监听通知机制 + ACL
这一节我们主要来看下文件系统的数据结构。
一、ZooKeeper 数据结构
ZooKeeper维护一个类似文件系统的数据结构(如下官方示意图),每一个子目录项(如app1)都被称作为znode(目录节点),和文件系统一样,我们能够自由的对一个znode进行CRUD,也可以在znode下进行子znode的CRUD,唯一不同的是,znode是可以存储数据的。
1.1 Znode类型
Znode的类型分为三类:
(1)持久节点(persistent node)节点会被持久化。
(2)临时节点(ephemeral node),客户端断开连接后,ZooKeeper会自动删除临时节点。
(3)顺序节点(sequential node),每次创建顺序节点时,ZooKeeper都会在路径后面自动添加上10位的数字,从1开始,最大是2147483647 (2^32-1)
每个顺序节点都有一个单独的计数器,并且单调递增的,由ZooKeeper的leader实例维护。
Znode实际上有四种形式,默认是persistent。
(1)PERSISTENT 持久节点: 如 create /test/a "hello" ,通过 create <path> <data>参数指定为持久节点
(2)PERSISTENT_SEQUENTIAL(持久顺序节点/s0000000001) ,通过 create -s <path> <data>参数指定为顺序节点
(3)EPHEMERAL 临时节点,通过 create -e <path> <data>参数指定为顺序节点
(4)EPHEMERAL_SEQUENTIAL(临时顺序节点/s0000000001) ,通过 create -s -e <path> <data> 参数指定为临时及顺序节点
ZooKeeper 3.5.x 中引入了 container 节点 和 ttl 节点(不稳定)
(1)container 节点用来存放子节点,如果container节点中的子节点为0 ,则container节点在未来会被服务器删除,定时任务默认60秒执行一次。
(2)ttl 节点默认禁用,需要通过配置开启, 如果ttl 节点没有子节点,或者 ttl 节点在 指定的时间内没有被修改则会被服务器删除。
二、Znode小示例
接下来我们来创建一下节点,来对于这个ZK的数据结构有一个更深的认识。使用命令: bin/zkCli.sh 连接上ZK服务,然后进行如下的操作。
2.1 PERSISTENT 持久节点
创建格式:create <path> <data>
这里创建一个/test的持久化节点,存放的数据是 ”hello“。创建成功之后可以使用ls / 进行查看已经创建的节点。对于持久节点我们断开这个客户端,然后重新连接上,然后在使用ls / 进行查看还是存在的。
当然我们可以在这个/test节点下创建n个子节点:
(1)ls -R 可以遍历节点的目录结构;
(2)get <path>可以获取到节点的数据;
另外对于我们的节点信息也是可以进行修改的,可以通过set <path> <data> 进行数据的数据,另外就是可以通过delete <path>进行数据的删除:
2.2 PERSISTENT_SEQUENTIAL持久顺序节点
创建格式:create -s <path> <data>
注意:
(1)如果有父节点的话,需要先创建父节点,不然直接创建的话,会报错。
(2)当然不带前缀也是可以的,直接create -s /seq/ , 这里最后的斜杆是要添加的,否则seq就会作为一个前缀来处理的。
(3)其它的修改、删除操作和持久节点的操作是一样的。
2.3 EPHEMERAL 临时节点
创建格式:create -e <path> <data>
(1)在mac下ctrl + c 断开客户端连接,然后在连接上,通过ls /查看,节点/ephemeral节点在断开连接之后自动被删除了。
(2)节点的生命周期是和当前的session绑定的。
(3)并不是当前session断开连接就立马被删除了,这个大概是30秒的延迟,所以立马登录上还是能够看到刚刚创建的临时节点,但是过了30秒之后还是会被删除的。
(4)临时节点不能有子节点,不管是什么类型的节点都不行,创建会报错:Ephemerals cannot have children: /ephemeral/test。
2.4 EPHEMERAL_SEQUENTIAL临时顺序节点
创建格式:create -e -s <path> <data>
2.5 container容器节点
container 节点用来存放子节点,如果container节点中的子节点为0 ,则container节点在未来会被服务器删除,定时任务默认60秒执行一次。
创建格式:create -c <path> <data>
(1)使用create -c创建了一个容器节点;
(2)在容器节点中创建了一些子节点,然后又将其子节点进行删除;
(3)大概过了60秒之后,由于容器节点没有子节点,所以被自动删除。
三、Znode属性
Znode兼具文件和目录两种特点。既像文件,又像目录一样可以作为路径标识的一部分。Znode维护着:
data:Znode存储的数据信息。
ACL:记录Znode的访问权限。
stat:包含Znode的各种元数据,比如事务ID、版本号、时间戳、大小等等。
child:当前节点的子节点引用。
把以上几类属性细化,又可以得到以下属性的细节:
cZxid:表示节点被创建时的事务 ID
mZxid:表示节点最后一次被修改时的事务 ID
ctime:表示节点创建时间
mtime:表示节点最后一次被修改的时间
pZxid:表示该节点的子节点列表最后一次被修改时的事务 ID。只有子节点列表变更才会更新 pZxid,子节点内容变更不会更新
cversion:表示子节点的版本号
dataVersion:表示内容版本号
dataLength:表示数据长度
numChildren:表示子节点数
ephemeralOwner:表示创建该临时节点时的会话 sessionID,如果是持久性节点那么值为 0。
3.1 Zxid
致使ZooKeeper节点状态改变的每一个操作都将使节点接收到一个Zxid格式的时间戳,并且这个时间戳全局有序。也就是说,每个对节点的改变都将产生一个唯一的Zxid。如果Zxid1的值小于Zxid2的值,那么Zxid1所对应的事件发生在Zxid2所对应的事件之前。实际上,ZooKeeper的每个节点维护着两个Zxid值,为别为:cZxid、mZxid。
(1)cZxid: 是节点的创建时间所对应的Zxid格式时间戳
(2)mZxid:是节点的修改时间所对应的Zxid格式时间戳
实现中Zxid是一个64位的数字,它高32位是epoch用来标识Leader关系是否改变,每次一个Leader被选出来,它都会有一个新的epoch。低32位是个递增计数。
3.2版本号
版本号是用来记录节点数据或者是节点的子节点列表或者是权限信息的修改次数。如果一个节点的version是1,那就代表说这个节点从创建以来被修改了一次。对节点的每一个操作都将致使这个节点的版本号增加。每个节点维护着三个版本号,分别为:
(1)dataVersion:节点数据版本号
(2)cversion:子节点版本号
(3)aversion:节点所拥有的ACL版本号
它通过对这些数据的管理来让缓存生效并且令协调更新。每当Znode中的数据更新后它所维护的版本号将增加。
四、小结
ZK数据结构特点:
(1)每个子目录都被称为znode, 每个znode是它所在路径的唯一标识, 如test1这个znode的标识为/test/test1。
(2)znode可以有子目录, 每个znode都可以存储数据。
(3)znode可以是临时节点, 如果客户端和服务器连接的session时效,znode将会被删除(这里注意,并不是立马删除,而是有一个30秒左右的延迟)。
(4)znode节点中数据如果被修改,可以被监控到,并通知对应的客户端(这个是监听通知机制,在后面我们会介绍到)。
购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287