数据模型
Zookeeper中的数据模型是一种树形结构,有一个固定的根节点(/),每一层级用斜杠分隔开,
只能用绝对路径进行访问,不能使用相对路径。
znode节点类型与特性
持久节点
该数据节点会一直存储在Zookeeper服务器上,即使创建该节点的客户端与服务端的会话关闭了,
该节点依然不会被删除,可以显示调用delete进行删除操作。
临时节点
如果节点数据不会一直存储在Zookeeper服务器上。当创建该临时节点的客户端会话因超时或发生异常而关闭时,
该节点也相应在Zookeeper服务器上删除,也可以使用delete显示删除。
有序节点
Zookeeper服务器会自动使用一个单调递增的数字作为后缀,追加到创建节点的后边。
Zookeeper的每个节点都包含一下内容:一个二进制数组(用来存储节点数据)、ACL访问控制信息、
子节点数据(因为临时节点不允许有子节点,其子节点字段为null)、节点状态字段stat。
节点的状态属性:
状态属性 | 说明 |
---|---|
czxid | 表示该数据节点被创建时的事物ID |
mzxid | 表示该节点最后一次被更新时的事物ID |
pzxid | 表示该节点的子节点列表最后一次被修改时的事务ID |
ctime | 表示该节点的创建时间 |
mtime | 表示该节点最后一次被更新的时间 |
version | 数据节点的版本 |
cversion | 子节点的版本 |
aversion | acl的版本号 |
ephemeraOwner | 创建临时节点的会话SessionID,如果是持久化节点,属性值为0 |
dataLength | 数据内容的长度 |
numChildern | 当前节点的子节点个数 |
使用Zookeeper实现锁
悲观锁
使用临时节点(有序节点)可以解决互斥问题,通过服务器添加监听时间来通知其他进程重新获取锁。
乐观锁
Zookeeper中有一个version属性就是用来实现了乐观锁机制中的校验,如果version无法匹配,便无法成功更新,
可以避免一些分布式更新的并发问题。
在Zookeeper底层实现中,服务端处理setDataRequest请求时,首先会调用checkAndIncVersion方法进行数据版本校验。
Zookeeper会从setDataRequest请求中获取当前的版本version,同时通过getRecordForPath方式获取服务器数据记录nodeRecord,
从中获取当前服务器上的版本信息currentversion,如果version为-1,表示该请求操作不实用乐观锁,忽略版本对比;如果version
不是-1,就将version和currentversion进行比对,如果相等,则进行更新操作,否则跑出BadVersionException异常。
为什么Zookeeper不能采用相对路径查找节点?
因为Zookeeper底层实现的时候,使用了一个HashTable,即ConcurrentHashMap
来作为key存储节点数据,这样就大大提高了Zookeeper的性能。