ZooKeeper在分布式领域,能够帮助解决很多很多的分布式难题,但是底层却只是依赖于两个主要的组件:ZNode文件/数据存储系统和watch监听系统,另外还有一大模块,就是ACL系统。本节我们介绍下znode文件/数据存储系统。
在 ZooKeeper 中,每一个数据节点都被称为一个ZNode,所有ZNode按层次化结构进行组织,形成一棵树。ZNode文件/数据存储系统的作用就是为分布式应用存储少量关键的核心状态数,ZNode既能挂载子节点,也能存储数据。
所以总结说来,ZNode即是文件夹又是文件的概念,但是在ZooKeeper这里面就不叫文件也不叫文件夹,叫ZNode,每个ZNode有唯一的路径标识,既能存储数据,也能创建子 ZNode,但是 ZNode只适合存储非常小量的数据,不能超过1M,最好小于1K。
ZNode的分类:
按照生命周期可以分为:
按照是否自带序列编号可以分为:
持久节点(PERSISTENT)
持久化znode节点,一旦创建这个znode节点,存储的数据不会主动消失,除非是客户端主动delete。
持久顺序节点(PERSISTENT_SEQUENTIAL)
自动增加自增顺序编号的znode节点,比如ClientA去zookeeper service上建立一个znode名字叫做 /zk/conf,指定了这种类型的节点后zk会创建 /zk/conf0000000000,ClientB再去创建就是创建 /zk/conf0000000001,ClientC是创建/zk/conf0000000002,以后任意Client 来创建这个znode都会得到一个比当前zookeeper命名空间最大znode编号+1的znode,也就说任意一个Client去创建znode都是保证得到的znode编号是递增的,而且是唯一的znode节点。
临时节点(EPHEMERAL)
临时znode节点,Client连接到zk service的时候会建立一个session,之后用这个zk连接实例在该session期间创建该类型的znode,一旦Client关闭了zookeeper的连接,服务器就会清除session,然后这个session建立的znode节点都会从命名空间消失。总结就是,这个类型的 znode的生命周期是和Client建立的连接一样的。比如ClientA创建了一个EPHEMERAL 的/zk/conf 的 znode 节点,一旦ClientA的zookeeper连接关闭,这个znode节点就会消失。整个zookeeper service命名空间里就会删除这个znode节点。
临时顺序节点(EPHEMERAL_SEQUENTIAL)
临时自动编号节点,znode节点编号会自动增加,但是会随session消失而消失。
注意点:
每个节点除了存储了数据内容的同时,还存储了节点本身的一些状态信息,我们在使用get命令获取数据节点时就能获取到这些信息。Zookeeper把这些信息封装在Stat类中:
状态属性 | 说明 |
---|---|
czxid | 表示该节点被创建时的事务ID |
mzxid | 表示该节点最后一次被更新时的事务ID |
ctime | 表示该节点被创建的时间 |
mtime | 表示该节点最后一次被更新的时间 |
version | 数据节点版本号 |
cversion | 子节点的的版本号 |
aversion | 节点的ACL版本号 |
ephemeralOwner | 创建该临时节点的会话sessionID,持久节点值为0 |
dataLength | 数据内容的长度 |
numChildren | 当前节点的子节点个数 |
pzxid | 表示该节点的子节点列表最后一次被修改时的事务ID |
每个数据节点具有三种类型的版本信息,对数据节点的任何更新操作都会引起版本号的变化:
版本类型 | 说明 |
---|---|
version | 当前数据节点数据内容的版本号 |
cversion | 当前数据节点子节点的版本号 |
aversion | 当前数据节点ACL变更版本号 |
Zookeeper中节点版本表示的是对数据节点的数据内容、子节点列表或是ACL信息的修改次数,以version为例:即使前后两次变更并没有使得数据内容的值发生变更,version的值依然会变更。
据内容、子节点列表或是ACL信息的修改次数,以version为例:即使前后两次变更并没有使得数据内容的值发生变更,version的值依然会变更。
而version属性是用来处理并发控制,实现乐观锁的写入校验的。在进行一次setDataRequest请求处理时,首先就会进行版本检查,Zookeeper会从setDataRequest中获取到当前请求的版本version,同时从数据记录nodeRecord中获取到当前服务器上该数据的最新版本currentVersion进行比对,如果两个版本不匹配,则会抛出异常。