【Hadoop】ZooKeeper:分布式系统的协调核心与一致性保障
本专栏文章持续更新,新增内容使用蓝色表示。
一、Zookeeper
ZooKeeper是一个针对大型分布式系统的可靠协调系统,专注于解决分布式环境下的资源管理、高可用性和一致性等关键问题。它通过提供配置维护、名字服务、分布式同步和组服务等核心功能,已成为分布式系统中不可或缺的基础组件。
目标:封装复杂易出错的关键服务(如 Hadoop 中的 NameNode、ResourceManager 等),为开发者提供简单易用、性能高效且功能稳定的系统接口。
1.1 核心特点
ZooKeeper具有以下关键特性:
【最重要】最终一致性:为所有客户端提供同一数据视图,保证集群数据的统一性。
可靠性:一旦消息被一台服务器接受,将被所有服务器接受。
实时性:通过sync()接口确保客户端获取最新数据(让Zookeeper强制地更新数据)。
等待无关性:慢速或失效客户端不会影响快速客户端的请求处理。
原子性:数据更新只能成功或失败,没有中间状态。
顺序性:所有服务器保持相同的消息发布顺序。
在传统架构中,Zookeeper 是众多分布式系统的协调核心,广泛应用于 HDFS、YARN、HBase、Kafka 等大数据组件,以及 Dubbo(阿里巴巴)、RocketMQ(前身为 MetaQ)等微服务与消息中间件。而 Kubernetes 等新一代系统则采用了内置的协调组件(如 etcd),将类似功能集成到了平台内部。
1.2 系统架构与角色
1.2.1 架构设计
ZooKeeper 采用集群架构,每个服务器(Server)在内存中存储完整的数据快照(Snapshot),并持久化事务日志(TxnLog)。集群启动或Leader失效时,通过 Zab 协议的 Fast Leader Election 机制选举 Leader。
所有数据更新操作(写请求)必须由 Leader 协调处理。Leader 会将其转换为一个事务提案(Proposal) 并广播给所有 Follower。只有当超过半数的 Follower 服务器成功持久化该提案后,Leader 才会提交(Commit)这个更新,并将其应用到内存数据中,随后通知客户端写操作成功。
这个过程可以类比于 MySQL InnoDB 集群的 半同步复制:一个事务必须在主库上完成 Prepare 阶段,并且至少被一个从库接收和记录(Relay Log)之后,主库才能提交(Commit)。这样可以确保即使主库宕机,新主库上也一定拥有最新的事务数据,从而保证了数据的可靠性。
1.2.2 角色分配
角色 | 职责描述 |
---|---|
领导者 (Leader) | 负责投票发起和决议,更新系统状态 |
跟随者 (Follower) | 接收客户端请求并返回结果,参与选举投票 |
观察者 (Observer) | 接收客户端连接,转发写请求到Leader,不参与投票 |
客户端 (Client) | 请求发起方 |
观察者的引入避免了大规模集群中所有节点参与投票导致的性能下降,类似于拥有绿卡者享有福利但无投票权的设计。
1.2.3 集群规模建议
ZooKeeper 集群服务器数量一般为奇数(3、5、7),不是偶数不行,而是偶数个选举会慢。
3台服务器集群:最多允许1台服务器故障;
4台服务器集群:同样最多允许1台服务器故障,但选举效率较低。
奇数节点设计提高了选举效率并确保了故障容错能力。
1.3. 数据写入流程
ZooKeeper的数据写入遵循严格的共识流程:
客户端请求:客户端向任意Follower发送写请求;
请求转发:Follower将写请求转发给Leader;
提案广播:Leader生成提案并向所有Follower广播;
确认响应:Follower处理提案后向Leader返回确认;
提交通知:当多数Follower确认后,Leader发送提交通知;
响应客户端:完成写入后向客户端返回成功响应。
这个过程确保了数据的强一致性和可靠性。
1.4 核心功能
1.4.1配置维护 (Configuration Management)
ZooKeeper 提供了一个高度可靠的中心化配置注册表。分布式系统中的各个节点可以从ZooKeeper 获取或监听其配置信息,从而保证整个系统配置的一致性。
示例:HBase 的元数据(如 hbase:meta 表的位置、当前活跃的 Master 节点地址)就保存在 ZooKeeper 中。RegionServer 和客户端都通过 ZooKeeper 来定位这些关键信息,从而正常运作。这使得 HBase 的组件可以无状态化,故障后能快速恢复。
1.4.2 名字服务 (Naming Service)
通过树形结构(ZNode)存储和管理分布式系统中的资源名称与地址映射关系,提供类似于 DNS 的服务发现功能。
1.4.3 分布式同步 (Distributed Synchronization)
这是ZooKeeper最核心的价值之一。它通过原子广播协议(Zab) 确保集群中所有服务器的状态(即数据)是强一致性的。
核心重要性:集群中各节点的元数据视图必须完全相同,否则就会发生“脑裂”(Split-Brain)等灾难性问题。例如,在一个主从集群中,如果两个节点都认为自己是主节点,同时对外提供服务,会导致数据被重复写入、相互覆盖,造成数据损坏和不一致。ZooKeeper 的机制确保了同一时刻只有一个客户端能成功创建代表“主节点”的临时节点,从而从根本上避免了脑裂。
1.4.4 组服务 (Group Membership)
管理分布式系统中节点的动态加入和离开,维护集群的成员列表。
补充:脑裂 (Split-Brain)
脑裂是分布式系统中的一个典型故障场景,指一个集群由于网络分区等原因,被分裂成两个或多个彼此无法通信的小集群。每个小集群都认为其他集群已经宕机,从而自行推举出新的主节点并继续对外提供服务,导致系统中有多个“主节点”并存,数据一致性被彻底破坏。
ZooKeeper 通过其 Zab 协议和“大多数原则” 来避免脑裂:
1)集群存活判定:一个 ZooKeeper 集群要能够对外提供服务,必须有多于半数的节点存活并且能相互通信。这也是为什么集群节点数推荐为奇数(3, 5, 7...)。
2)写请求处理:所有写请求都必须由 Leader 处理,并且必须得到大多数(Majority) Follower 的确认才算成功。
3)网络分区下的自保:假设一个5节点的集群被分裂成两个部分(3节点 vs 2节点)。拥有3个节点( majority)的部分可以继续选举Leader并对外服务,因为它代表了集群的大多数。而只有2个节点( minority)的部分由于无法达到多数确认,会自动停止服务,从而避免了出现两个都能对外服务的“脑裂”集群。
因此,HBase、Kafka 等系统将其核心元数据(如谁才是主节点)托管给 ZooKeeper,正是利用了其分布式同步和一致性能力,来确保整个集群状态的唯一性和正确性,从根本上规避了脑裂风险。
二、应用场景
2.1 配置管理
分布式环境下,ZooKeeper解决了配置文件管理和同步问题(在任意节点上修改都可以,不一定是master):
将配置信息写入指定的Znode;
各个节点监听该Znode的变化;
配置修改后实时同步到所有节点。
典型应用:Hadoop集群配置一致性维护。
2.2 集群管理
ZooKeeper 提供实时节点状态监控:
节点信息写入特定 Znode;
监听Znode变化获取实时状态;
根据节点状态进行系统调整。
典型应用:HBase中Master状态监控与选举。
2.3 分布式通知/协调
ZooKeeper 支持服务状态感知和协调(分布式环境中,服务经常需要知道它所管理的子服务的状态):
实现心跳检测机制;
提供发布/订阅模式的信息推送;
确保管理者实时了解被管理服务状态。
典型应用:NameNode监控DataNode状态,ResourceManager监控NodeManager状态。
2.4 分布式锁
ZooKeeper的强一致性特性使其成为理想的分布式锁实现方案:
独占锁:多个客户端创建相同Znode,只有一个成功;
时序锁:创建临时顺序Znode(EPHEMERAL_SEQUENTIAL)控制访问时序。
2.5 分布式队列
ZooKeeper支持两种分布式队列模式:
同步队列:等待所有成员到达后才可用;
FIFO队列:按照先进先出原则进行入队和出队操作,例如实现生产者和消费者模型。
同步队列实现:为job创建目录,为每个完成的task创建临时Znode,当临时节点数达到task总数时标记job完成。
如有问题或建议,欢迎在评论区中留言~