数据模型
ZooKeeper的数据模型由“数据节点”(ZNode)组成,ZNode是ZooKeeper中最小的数据单元,每个ZNode上既可以保存数据,也可以挂载子节点。
ZooKeeper 中的数据模型是一种树形结构,像是电脑里的文件系统,有一个根目录,下面还有很多子目录。
节点类型与特性
持久节点
因为一旦将节点创建为持久节点,该数据节点会一直存储在ZooKeeper服务器上。
即使创建该节点的客户端与服务端的会话关闭了,该节点依然不会被删除
如果想删除持久节点,就要显式调用 delete 方法执行删除。
临时节点
如果将节点创建为临时节点,那么该节点数据不会一直存储在 ZooKeeper 服务器上。当创建该临时节点的客户端会话因超时或发生异常而关闭时,该节点也相应在 ZooKeeper 服务器上被删除。
临时节点的生命周期与创建该节点的客户端会话有关。
当然我们也可以用delete方法手动删除。
有序节点
有序节点并不算是一种单独类型的节点,而是在之前提到的持久节点和临时节点特性的基础上,增加了一个节点有序的性质。
在ZooKeeper中,每个父节点都会为它下面的一级子节点维护一份顺序,用于记录子节点的先后顺序。
基于该先后顺序,在创建子节点的时候,ZooKeeper会专门将给定节点名加上一个数字后缀,作为一个全新的、完整的节点名。
比如说一个客户端创建了一个路径为 registry/temp- 的有序节点,那么 ZooKeeper 将会生成一个序号并追加到该节点的路径后,最后该节点的路径为 registry/temp-1。
有序节点分为持久有序节点和临时有序节点。
前文总结
虽然前面介绍的这几种数据节点的类型不同,但 ZooKeeper 中的每个节点都维护有这些内容:一个二进制数组(byte data[]),用来存储节点的数据、ACL 访问控制信息、子节点数据(因为临时节点不允许有子节点,所以其子节点字段为 null),除此之外每个数据节点还有一个记录自身状态信息的字段 stat。
节点状态信息
我们来看每个数据节点记录自身状态信息的字段:stat
数据节点的版本
每个数据节点有 3 种类型的版本信息,对数据节点的任何更新操作都会引起版本号的变化。
ZooKeeper 的版本信息表示的是对节点数据内容、子节点信息或者是 ACL 信息的修改次数。
这三种类型的版本信息分别对应stat字段中的version/cversion/aversion
基于version的乐观锁机制
乐观锁基本可以分为读取、校验、写入三个步骤。
CAS(Compare-And-Swap),即比较并替换,是一种经典的乐观锁实现。CAS 有 3 个操作数,内存值 V,旧的预期值 A,要修改的新值 B。当且仅当预期值 A 和内存值 V 相同时,将内存值 V 修改为 B,否则什么都不做。
在 ZooKeeper 中的 version 属性就是用来实现乐观锁机制中的“校验”的,ZooKeeper 每个节点都有数据版本的概念,在调用更新操作的时候,假如有一个客户端试图进行更新操作,它会携带上次获取到的 version 值进行更新。
如果请求的version值为-1,表明不使用乐观锁机制;否则就拿来与该数据节点的最新版本currentVersion比较,如果两者不相等,就会抛出
BadVersionException异常。
翻译成SQL 语言就是: update table set nodeNate=newValue where version=version
总结
本文介绍了ZooKeeper的数据模型、数据节点类型、数据状态信息和节点版本等内容,顺带着说了一下乐观锁。在ZooKeeper的知识点中,我觉得这些是最基本的内容,需要好好掌握。
接下来可能会写一篇关于ACL机制的文章。原本两个月以前就想学习ZooKeeper并输出博客的,但由于种种原因吧,停止了更新;不过趁着这一次的七日打卡活动,督促自己输出文章,而输出又会倒逼输入(学习),其实挺奇妙的。
总之,刚开始写作不到半年,文笔和表达都很一般,但是很感恩掘金提供了良好的创作平台,我一定会坚持写一下去的,谢谢!