理解 ZooKeeper 集群的读写流程是掌握其工作原理的关键。其核心设计在于 “写操作集中化,读操作分布式”,以此来保证强一致性。
详细流程说明
1. 写请求流程
写请求(如 create, delete, setData)必须由 Leader 协调,以确保所有节点按相同顺序执行相同操作,这是实现 ZAB 协议 和强一致性的基础。
步骤分解:
客户端连接与请求发送:
客户端随机连接到集群中的任何一个节点(可能是 Leader、Follower 或 Observer)。
客户端发送写请求(例如,create /path data)。
请求转发:
如果客户端连接的是 Follower 或 Observer,该节点会将写请求转发给 Leader。只有 Leader 能处理写请求。
Leader 发起提案:
Leader 接收到写请求后,将其转换为一个事务提案。
Leader 为这个提案分配一个全局唯一的、单调递增的 ZXID。
Leader 将这个提案 广播 给所有的 Follower 节点(Observer 不参与)。
Follower 确认提案:
每个 Follower 接收到提案后,会将其持久化到本地的事务日志中(写入磁盘),以确保数据不会丢失。
一旦持久化成功,Follower 会向 Leader 发送一个 ACK 确认消息。
Leader 提交事务:
Leader 等待,直到收到超过半数的 Follower 的 ACK。
一旦达到条件,Leader 就认为这个提案已经达成共识,可以提交了。
Leader 更新自身的内存数据。
Leader 广播提交:
Leader 向所有 Follower 和 Observer 发送一个 COMMIT 消息。
Follower/Observer 提交事务:
所有 Follower 和 Observer 接收到 COMMIT 消息后,才更新各自的内存数据。
响应客户端:
Leader 向最初接收请求的节点(如果请求被转发过)发送成功响应,最终由该节点将成功结果返回给客户端。
2. 读请求流程
读请求(如 getData, getChildren, exists)的处理则简单高效得多,因为它们是直接在接收请求的节点本地处理的。
步骤分解:
客户端连接与请求发送:
客户端随机连接到集群中的任何一个节点(Leader、Follower 或 Observer)。
客户端发送读请求(例如,getData /path)。
本地数据处理:
该节点直接查询自己的本地内存数据库来获取数据。
无需与集群中的其他节点进行任何通信。
响应客户端:
节点立即将查询结果返回给客户端。
关键特性与对比
特性 |写请求 |读请求
处理节点 |必须由 Leader 处理 |可由任意节点处理(Leader/Follower/Observer)
一致性 |强一致性。所有节点按相同顺序执行,客户端读到的一定是最新数据。 |默认强一致性。由于读的是本地内存(已通过写流程同步),所以总能读到最新数据。
性能 |延迟较高。需要分布式事务、磁盘写入和多数派确认。 |延迟极低,吞吐量高。无网络通信和磁盘I/O(除首次同步)。
扩展性 |差。所有写压力都在 Leader 上。 |极佳。可以通过增加 Follower 和 Observer 来水平扩展读能力。
通信模式 |复杂。涉及与所有 Follower 的多轮通信(两阶段提交)。 |简单。无额外通信。
重要补充:观察者
从流程中可以看出,Observer 在写流程中只负责从 Leader 同步数据并更新自身内存,不参与投票。
在读流程中,它和 Follower 一样直接提供服务。这使得增加 Observer 可以在不影响写性能的前提下,无限扩展集群的读能力。
总结
写流程是一个分布式共识过程,保证了数据的可靠性和一致性,但代价是较高的延迟。
读流程是一个本地化操作,利用了内存计算的优点,提供了极高的性能和可扩展性。
这种读写分离的架构设计,使得 ZooKeeper 非常适合于 “读多写少” 的协调场景,例如配置管理、服务发现、元数据存储等。
04-20
598
598
11-23
1186
1186
05-13
1173
1173

被折叠的 条评论
为什么被折叠?



