【Zookeeper读书笔记-1】系统模型

ZK模型分成数据模型,节点特性,版本,Watcher,ACL五个部分。

 

1 数据模型

树形结构:每个节点成为ZNode,是数据的最小单元,每个节点可以存放数据或者是子节点。

事务ID:ZXID,每次对服务器状态进行操作,就会分配全局的事务ID

2 节点类型

根据节点生命周期长短分成持久节点,临时节点,顺序节点

持久节点:一直存在服务端,直到手动删除。

临时节点:生命周期是客户端的会话失效周期,不是TCP断开连接。临时节点只能作为叶子节点,不能基于临时节点创建子节点。

顺序节点:节点可能还表现为顺序特性,即节点在父节点列表中是否标记创建顺序。

3 状态信息

节点信息包含节点数据内容以及状态信息。

czxid:reated ZXID,表示该节点被创建时的事务ID。
mzxid:Modified ZXID,表示该节点最后一次被更新时的事务ID。
ctime:表示节点被创建的时间。
mtime:表示该节点最后一次被更新时的时间。
version:数据节点的版本号。节点被创建后,被更新过的次数,即使更新的内容与原内容相同,也视为一次更新。
cversion:子节点的版本号。
aversion:节点的ACL版本号。
ephemeralOwner:创建该临时节点的会话的SessionID。如果该节点为持久节点,那么这个属性值为0。
dataLength:数据内容的长度。
numChildren:当前节点的子节点个数。
pzxid:表示该节点的子节点列表最后一次被修改时的事务ID。只有子节点列表变更了才会变更pzxid,子节点内容变更不会影响pzxid。

4 Watcher数据变更通知

一对多的发布订阅模式,客户端向服务端注册watcher,监听某一特定主题的对象,当主题对象自身发生变化时,会通知所有的订阅者。

4.1 watcher基础

Watcher机制包括:客户端,客户端WatcherManager,服务端。

客户端向服务端注册watcher同时会把watcher对象存入WatcherManager中,当服务端触发Watcher事件后,会向服务端发送通知,服务端从WatcherManager中取出对应的Watcher对象,执行回调逻辑。

Watcher特性包含:

  1. 注册一次性:服务端或者客户端的watcher一旦被触发,就会被删除。如果需要监听,就要反复注册。否则一些更新比较频繁的节点,每次变动都要不断地将通知反馈给客户端,对与网络以及服务端性能影响很大。
  2. 客户端Watcher回调是串行同步的,保证了每个wathcer的顺序。
  3. 轻量级watcher。WatchedEvent是Watcher机制的最小通知单元,只包含了通知状态,事件类型,节点路径,不给出具体的变化内容,需要客户端自己去相应节点获取变化的内容,保证了客户端服务端交互的数据量级。

4.2 Watcher事件

注意:

NodeDataChanged:与dataVersion一致,即使变更内容前后一样,也会触发此事件。

NodeChildrenChanged:所关注的节点的子节点列表有变化。这里说的变化是指子节点的个数和组成,具体到子节点内容的变化是不会通知的。

4.3 process回调方法

WatchEvent包含三个属性:事件状态keeperstate,事件类型eventType,节点路径path。

abstract public void process(WatchedEvent event);

/**
 *  A WatchedEvent represents a change on the ZooKeeper that a Watcher
 *  is able to respond to.  The WatchedEvent includes exactly what happened,
 *  the current state of the ZooKeeper, and the path of the znode that
 *  was involved in the event.
 */
@InterfaceAudience.Public
public class WatchedEvent {
    final private KeeperState keeperState;
    final private EventType eventType;
    private String path;
}

4.4 Watcher工作机制

watcher注册机制包括:客户端注册Watcher,服务端处理Watcher,客户端回调Watcher。

4.4.1 客户端注册Watcher

1. 创建zk客户端对象实例时注册watcher,这个 Watcher 将作为整个 ZooKeeper 会话期间的默认 Watcher,它会一直被保存在客户端 ZKWatchManager 的 defaultWatcher 里面。(getData, getChildren, exists方法中也可以注册watcher)。

2. 例如getData注册Watcher后,客户端会向当前的request标记,设置为“使用watcher监听”,同时封装WatcherRegistration对象用于暂时保存数据节点路径和wathcer对应关系。

3. WatchRegistration被封装成Packet对象,放入发送队列等待客户端发送。客户端没有把Watcher对象发送给服务端,只是将request与requestHeader两个属性序列化传输,否则服务端就容易出现内存紧张甚至溢出的危险。

4. ZKWatcherManager.dataWatches是Map<String, Set<Watcher>>保存数据节点路径与Watcher对象关系。

4.4.2 服务端处理Watcher

对于注册 Watcher 请求,FinalRequestProcessor 的 ProcessRequest 方法会判断当前请求是否需要注册 Watcher,如果为 true,就会将当前的 ServerCnxn 对象和数据节点路径传入 getData 方法中去。ServerCnxn 是一个 ZooKeeper 客户端和服务器之间的连接接口,代表了一个客户端和服务器的连接,我们后面讲到的 process 回调方法,实际上也是从这里回调的,所以可以把 ServerCnxn 看作是一个 Watcher 对象。数据节点的节点路径和 ServerCnxn 最终会被存储在 WatchManager 的 watchTable 和 watch2Paths 中。
WatchManager 负责 Watcher 事件的触发,它是一个统称,在服务端 DataTree 会托管两个 WatchManager,分别是watchTable和 watch2Paths,分别对应数据变更 Watcher 和节点变更 Watcher。

当DataTree中节点数据内容或版本发生变化或节点变更时,会调用相应方法去触发 WatchManager 的 triggerWatch 方法,该方法返回 ZNODE 的信息,自此进入到回调本地 process 的序列。

4.4.3 客户端回调Watcher

SendThread的response()方法负责接收这个客户端事件通知。首先会对replyHeader中xid进行判断,如果是-1,则说明是一个通知类型的响应。作以下处理:

1.反序列化:ZooKeeper客户端接到请求后,首先将字节流转换成WatcherEvent对象。

2.处理chrootPath:如果客户端设置了chrootPath属性,那么需要对服务端传过来的完整的节点路径进行chrootPath处理,生成客户端的一个相对节点路径。

3.还原WatchedEvent:将WatcherEvent对象转换成WatchedEvent。

4.回调Watcher:将WatchedEvent对象交给EventThread线程,在下一个轮询周期中进行Watcher回调。

5 ACL保障数据安全

用于对节点的权限进行控制,一个有效的ACL信息包含:权限模式(Scheme),授权对象(ID),权限(Permission),即"scheme:ID:permission"。

 

参考:

https://www.cnblogs.com/shamo89/p/9787176.html

图比较详细

https://www.cnblogs.com/ZhuChangwu/p/11593642.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章