《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

《从Paxos到Zookeeper》-ZooKeeper技术内幕–系统模型

每个数据节点被称为Znode,他们按树的形式组织。

事物ID

事务操作是能够改变ZooKeeper服务器状态的操作,包括数据节点创建,数据更改,客户端会话创建与失效,对于每个事务操作,ZooKeeper都会分配一个全局唯一的事务ID,用ZXID来表示。

节点特性

节点类型:持久节点、持久顺序节点、临时节点、临时顺序节点

节点状态信息

通过get命令可以看到节点状态信息

《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

版本-保证分布式数据原子性操作

《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

表示的是对数据节点的内容、子节点列表、或是节点ACL信息的修改次数。即使内容没变,执行了变更命令,还是会version+1。ZooKeeper用它作为乐观锁(setDataRequest的源码中可以看出来)。

Watcher-数据变更通知

ZooKeeper允许客户端向服务端注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。

《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

Watcher在使用上的几个要素: Watcher接口、WatcherEvent、process方法。
WatcherEvent是极简的,只有type,stat,path三个变量。

Watch的工作机制

《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

客户端发送

客户端将在getData时传入的Watcher封装为WatchRegistration。Packet是一个最小的通信单元,可以看到WatchRegistration是Packet的属性,被封装到了Packet中。ClientCnxn负责将Packet发送到ZooKeeper中,收到服务端的响应后,客户端会从WatchRegistration提取出Watch放到ClientWatchManager中。

服务端处理
ServerCnxn存储

ZooKeeper接收到请求后,会先判断当前请求是否需要注册Watcher;为true时,ZooKeeper就会认为当前客户端请求需要进行Watcher注册,于是就会将当前的ServerCnxn对象和数据节点路径传入getData方法中去。可以把ServerCnxn看作是一个Watcher对象。数据节点的节点路径和ServerCnxn最终会被存储在WatchManager的watchTable和watch2Paths。

Watcher触发

NodeDataChanged事件的触发条件是Watcher监听的对应数据节点的数据内容发生变更,当调用setData方法后,在对指定节点进行数据更新后,通过调用WatchManager的triggerWatch方法来触发相关的事件。无论是哪种WatchManager(dataWatches还是childWatches),触发逻辑都是一样的。

1.先封装WatchedEvent。2.查询Watcher,根据数据节点的节点路径从watchTable中取出对应的Watcher。如果没有Watcher,说明没有任何客户端在该数据节点上注册过Watcher,直接退出。找到会将Watcher提取出来,同时在watchTable和watch2Paths中将其删除,由此可以看出Watcher在服务端是一次性的,即触发一次就失效。3.之前我们提过ServerCnxn其实就是一个Watcher,所以其实就是调用的ServerCnxn.process方法,把WatchEvent传送到客户端。

客户端回调Watcher

SendThread.readResponse来处理服务端的响应。

《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

还原出WatchedEvent,将它交给EventThread线程。

《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

queueEvent根据事件从ZKWatchManager中取出所有相关Watcher。取出后,调用了remove:
《从Paxos到Zookeeper》-ZooKeeper技术内幕--系统模型

说明客户端的Watch也是一次性的。将获取到的Watcher放入waitingEvents这个队列中去。EventThread的run方法会不断对该队列进行处理:不断地冲队列中取出一个Watcher,并串行同步处理,调用Watcher的process方法。