1. 核心概念
Watch 机制是 ZooKeeper 实现分布式协调的关键。它允许客户端向服务端注册一个 Watcher(监听器),当服务端指定节点的状态发生变化(如数据改变、节点删除、子节点变化)时,服务端会向客户端发送一个事件通知。
这是一种发布/订阅(Publish/Subscribe)模式。
2. 关键特性(面试必考)
- 一次性触发 (One-time trigger):
- 这是最容易踩坑的地方。服务端发送通知后,该 Watch 就失效了。如果需要持续监听,客户端必须在处理通知的回调逻辑中再次注册 Watch。
- 注:ZooKeeper 3.6.0+ 引入了持久监听(Persistent Watcher),但在面试中通常默认讨论经典的一次性 Watch。
- 推拉结合:
- ZooKeeper 的 Watch 是推(Push)模式。服务端主动推送事件通知给客户端。
- 客户端收到通知后,通常需要主动拉(Pull)取最新的数据。
- 轻量级:
- 通知内容非常简单,只包含“发生了什么事件”(Event Type)和“哪个节点发生的”(Node Path),不包含变更后的具体数据。
3. 工作流程与原理
- 客户端注册:
- 客户端调用
getData("/node", true)或exists("/node", watcher)。 - 客户端将 Watcher 对象存储在本地的
ZKWatchManager中。 - 客户端向服务端发送请求,标记该路径需要监听。
- 客户端调用
- 服务端处理:
- 服务端接收请求,将 ServerCnxn(客户端连接对象)存储在对应的
WatchManager中。
- 服务端接收请求,将 ServerCnxn(客户端连接对象)存储在对应的
- 事件触发:
- 当
/node数据发生变更,服务端在WatchManager中找到所有监听该路径的 ServerCnxn。 - 服务端构造一个
WatchedEvent对象,发送给客户端。 - 服务端移除该 Watch(体现了一次性)。
- 当
- 客户端回调:
- 客户端收到通知,从本地
ZKWatchManager中取出对应的 Watcher 对象。 - 执行 Watcher 的
process()方法。
- 客户端收到通知,从本地
4. 常见 Watch 事件类型
NodeCreated:节点创建。NodeDeleted:节点删除。NodeDataChanged:节点数据内容更新。NodeChildrenChanged:子节点列表变化(增删子节点)。
5. 总结
面试官:请讲讲 ZooKeeper Watch 机制。
候选人: ZooKeeper 的 Watch 机制是一种基于发布/订阅模式的分布式通知机制。
它的核心流程是:客户端在读取数据时(如
getData)注册 Watch,服务端记录下来。当数据发生变更时,服务端主动推送通知给客户端,客户端触发回调逻辑。它有三个关键特性:
- 一次性:触发后立即失效,需要重复注册。
- 异步性:通知发送是异步的,不阻塞写操作。
- 轻量级:只通知“发生了变化”,不包含具体数据,客户端需要再次主动拉取。
这种机制非常适合用于配置中心(配置变更通知)和服务注册发现(服务上下线通知)。