zookeeper介绍
ZooKeeper 概述
什么是 ZooKeeper?
ZooKeeper 是 Apache 基金会开源的一个高性能、高可用、强一致性的分布式协调服务。它主要解决的是分布式系统中的数据一致性问题和状态同步问题。在大型分布式系统中,服务节点会频繁上下线,存在网络延迟、节点宕机、数据不一致等诸多问题。如果没有一个“统一协调者”,各个服务之间将无法有效协作。
ZooKeeper 设计为一个轻量级、高可靠性的“协调中心”,主要用于:服务注册与发现、配置管理、分布式锁、主节点选举等场景。它本身是一个小型的分布式文件系统,但这个文件系统的设计目标不是高并发读写,而是快速、准确的状态通知与元数据维护。
简单来说,ZooKeeper 是分布式系统的“指挥中心”,它不提供计算能力,不负责复杂业务,而是保证各个服务节点“彼此了解彼此”的状态。
ZooKeeper 的主要功能?
1.命名服务(Name Service)
在分布式架构中,服务的地址、端口等信息可能动态变化。如果服务之间直接通过硬编码的 IP 地址通信,会导致部署和扩展极其困难。
ZooKeeper 通过树形节点结构,为每个服务提供唯一的命名路径,服务注册到这个路径下,其他客户端可以通过路径发现最新的服务地址。
/services/user-service -> 192.168.1.10:8080/services/order-service -> 192.168.1.11:8080
这样,服务消费者只需要知道路径 /services/user-service
,而不用关心实际 IP 地址是否变化。
2.配置管理
ZooKeeper 可以集中管理分布式系统中的配置文件,所有客户端读取的都是 ZooKeeper 上的配置,且支持动态监听配置变更。
/config/max_connections -> 5000/config/timeout -> 3000ms
当配置更新时,ZooKeeper 会通过 Watcher 机制自动通知所有客户端,不需要手动同步,也不需要重启。
3.分布式锁
ZooKeeper 利用顺序临时节点可以简单高效地实现分布式锁。
实现流程:
-
每个客户端创建
/lock/lock-XXXX
顺序节点 -
谁创建的节点编号最小,谁获得锁
-
如果锁节点被删除,后续节点自动被唤醒
优点:
-
实现简单,无需复杂同步算法
-
自动释放(客户端断连,节点自动清除)
-
天然支持公平锁(按顺序排队)
4.主节点选取(Master Election)
在很多分布式系统中(如 HDFS、Kafka),需要有一个 Master 节点,负责核心业务。ZooKeeper 提供高可靠的主节点选举能力。
选举原理:
-
所有节点创建临时顺序节点
-
最小编号的节点成为 Master
-
Master 挂了,ZooKeeper 自动通知下一节点接管
优点:
-
自动选主,容灾能力强
-
节点上下线自动感知
-
选举过程高效可靠
ZooKeeper 的典型应用场景?
ZooKeeper 已广泛应用于 HDFS、Kafka、HBase、Dubbo、gRPC 等分布式系统,是现代微服务架构的重要基础组件。
Zookeeper架构与部署
单机模式 vs 集群模式
ZooKeeper 支持单机模式和集群模式两种部署方式,适用于不同场景需求:
集群规模与容错能力
ZooKeeper 要求集群节点数量为奇数,以确保能够选出多数节点
最大容错数 = (n - 1) / 2
,其中 n
是集群节点总数。
-
生产环境建议至少 3 个节点,5 个更稳定。
-
若需高并发读请求,可加入若干 Observer 节点,提升读性能但不影响一致性。
-
所有集群节点必须配置一致的
zoo.cfg
配置文件中的 server 列表。
ZooKeeper 集群架构
ZooKeeper 集群使用经典的主从架构(Leader-Follower 架构),为了提高系统可扩展性和读性能,还引入了Observer(观察者)节点。整个集群以一个 Leader 为核心,配合多个 Follower 与 Observer 节点协同工作。
节点类型及职责划分
ZooKeeper 的配置文件解析(zoo.cfg
)
ZooKeeper 的运行依赖一个名为 zoo.cfg
的配置文件,位于其安装目录下的 conf/
目录中(通常路径为 conf/zoo.cfg
),该文件控制着 ZooKeeper 的核心运行参数,如数据目录、端口号、会话超时时间,以及集群节点信息等。
配置文件的基本结构
zoo.cfg
是一个标准的键值对(key=value
)格式的文本文件,内容结构简单,注释使用 #
开头。
tickTime=2000initLimit=10syncLimit=5dataDir=/var/lib/zookeeper/datadataLogDir=/var/lib/zookeeper/logclientPort=2181server.1=192.168.1.1:2888:3888server.2=192.168.1.2:2888:3888server.3=192.168.1.3:2888:3888
关键配置项解释
基础配置项(单机或集群通用)
tickTime
initLimit
syncLimit
dataDir
myid
的文件(集群模式必备)。dataLogDir
dataDir
。分离可提高性能。clientPort
2181
。客户端通过此端口进行连接和访问。集群配置项(分布式部署专用)
server.X=A:B:C
X
是 myid,A
是主机 IP 或域名,B
是选举通信端口,C
是数据同步端口。server.1=192.168.1.1:2888:3888
-
server.1:该节点的 myid 是 1;
-
192.168.1.1:该节点的主机地址;
-
2888:Follower 用于与 Leader 建立连接的端口;
-
3888:用于 Leader 选举的通信端口。
每个参与选举的节点都必须在配置文件中显式列出所有集群成员。
myid 文件说明(集群部署必备)
对于每个集群节点,ZooKeeper 要求在 dataDir
目录中存在一个名为 myid
的文件,内容是该节点的 ID(整数),用于标识 server.X
中的 X。
-
dataDir=/var/lib/zookeeper/data
-
在该目录下需创建文件
/var/lib/zookeeper/data/myid
,文件内容为1
,表示这是server.1
。
Linux环境下的Zookeeper安装与部署
①安装java环境
sudo apt updatesudo apt install default-jdkjava -version
②下载安装 ZooKeeper
下载官方二进制包
Apache ZooKeeper
cd /optsudo wget https://downloads.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gzsudo tar -xzf apache-zookeeper-3.8.4-bin.tar.gzsudo mv apache-zookeeper-3.8.4-bin zookeeper
③创建数据目录和日志目录
ZooKeeper 默认需要 dataDir
保存其事务日志和内存快照:
sudo mkdir -p /opt/zookeeper/datasudo mkdir -p /opt/zookeeper/logssudo chown -R $USER:$USER /opt/zookeeper
④配置 ZooKeeper
进入 ZooKeeper 目录,复制配置模板:
cd /opt/zookeeper/confcp zoo_sample.cfg zoo.cfg
编辑 zoo.cfg
文件:
nano zoo.cfg
⑤启动 ZooKeeper 服务端
进入 ZooKeeper 根目录:
cd /opt/zookeeperbin/zkServer.sh start
查看状态:
bin/zkServer.sh status
输出示例:
ZooKeeper JMX enabled by defaultUsing config: /opt/zookeeper/bin/../conf/zoo.cfgMode: standalone
⑥验证连接
你可以用自带客户端连接:
bin/zkCli.sh -server 127.0.0.1:2181
连接后可以尝试:
create /testnode \"hello\"get /testnode
常用命令汇总
服务端管理命令
zkServer.sh start
zkServer.sh stop
zkServer.sh restart
zkServer.sh status
客户端启动命令
zkCli.sh
localhost:2181
zkCli.sh -server ip:port
zkCli.sh -server ip1:port1,ip2:port2,...
客户端交互命令(在 zkCli.sh 中使用)
help
ls /path
create
get
set
delete
stat
exists
connect
quit
ZooKeeper基本原理
ZooKeeper 数据模型(ZNode)
ZooKeeper 提供树形数据结构,每个节点叫 ZNode,类似 Linux 文件系统。
特性:
-
节点路径全局唯一
-
节点存储小数据(最大 1MB)
-
节点支持版本控制
-
支持四种节点类型
树形结构示意:
/├── config│ ├── db -> mysql://192.168.1.10│ └── timeout -> 3000├── services│ ├── user-service -> 192.168.1.20│ └── order-service -> 192.168.1.21└── locks ├── lock-00000001 └── lock-00000002
会话机制与临时节点
ZooKeeper 的核心设计理念之一是会话机制(Session),它在客户端和 ZooKeeper 服务端之间维护了一个状态连接,并为分布式系统中的一致性和资源管理提供了基础保障。
会话:
会话是客户端与 ZooKeeper 服务端之间建立的长期连接,基于 TCP 连接并维持心跳(心跳机制是指客户端周期性向服务器发送心跳包,证明自己仍在线)。每个会话有以下关键属性:
-
会话 ID(sessionId):ZooKeeper 生成的唯一标识符,用于区分不同客户端会话。
-
会话超时时间(sessionTimeout):客户端与服务端约定的超时时间,默认 30000ms(30秒),指客户端在这段时间内未发送心跳,服务器视为客户端失联。
-
会话状态:
-
连接中(CONNECTED):客户端已成功与服务器建立会话。
-
断开连接(DISCONNECTED):客户端和服务器连接暂时中断,客户端可尝试重连。
-
重连中(RECONNECTED):客户端断线后短时间内恢复连接,保留会话信息。
-
会话生命周期:
会话的生命周期决定了 ZooKeeper 如何管理客户端资源,尤其是临时节点(Ephemeral Node) 的创建和删除。
会话与临时节点的关系:
临时节点是会话的产物,具有强绑定性:
-
临时节点由某个会话创建。
-
会话关闭(正常或异常超时),其对应的所有临时节点都会被 ZooKeeper 自动删除。
-
这确保了分布式系统中“会话绑定资源自动释放”的特性,避免资源泄漏。
临时节点的典型应用场景:
-
分布式锁
通过客户端创建临时节点来表示锁的持有。只有会话存活,临时节点存在,锁才有效;会话失效,临时节点自动删除,锁释放。
-
主节点选举
选举过程中,候选者创建临时顺序节点;节点存在即表示候选者活跃,会话过期则自动放弃竞选,系统可以重新选举。
-
资源绑定和自动释放
会话绑定的临时节点可用来表示客户端的资源状态,客户端断开,资源自动回收,确保系统一致性。
ZAB 协议与一致性保障
在分布式系统中,一致性(Consistency)是核心挑战之一。ZooKeeper 作为一个强一致性(CP 模型)系统,依靠其自研的ZAB 协议(ZooKeeper Atomic Broadcast) 来保证多个副本之间的数据一致。ZAB 协议专为 ZooKeeper 构建,具有高效、高可用、高一致性的特性,能够确保即使在节点崩溃、网络分区等复杂环境下,也能提供原子广播与顺序一致性。
ZAB 协议的流程(写操作)
Client → Follower → Leader → Proposal → Follower ACK → Commit
-
客户端发起写请求
-
客户端将写请求发送给任意一个 ZooKeeper 服务器(通常是本地最近的 Follower)。
-
-
请求转发至 Leader
-
Follower 将请求转发给当前集群中的 Leader 节点,由 Leader 统一处理所有写请求。
-
-
Leader 生成 Proposal(提案)
-
Leader 为该请求生成一个事务提案,标记一个全局唯一的 事务 ID(zxid)。
-
zxid(ZooKeeper Transaction ID)是一个 64 位的编号,前 32 位为 epoch(Leader 选举周期),后 32 位为事务计数器,确保全局有序。
-
-
Proposal 广播至所有 Follower
-
Leader 将生成的 Proposal 广播给所有 Follower,等待它们的确认(ACK)。
-
-
半数以上 Follower 返回 ACK
-
Leader 收到超过半数节点的 ACK 后,认为该 Proposal 达成共识。
-
-
Leader 发送 Commit
-
Leader 向所有节点广播 Commit 指令,所有节点应用该事务,事务提交成功。
-
-
客户端接收到响应
-
一旦写请求被 Commit,ZooKeeper 才会向客户端返回成功结果,保证事务已被大多数节点写入。
-
ZAB 的两种工作模式
-
恢复模式(Recovery Mode)
-
用于集群启动或 Leader 重新选举期间。
-
系统会从各节点同步日志,选出最新的 Leader,确保状态最大化一致。
-
一旦完成同步,切换至广播模式。
-
-
广播模式(Broadcast Mode)
-
正常运行状态下,处理客户端请求。
-
Leader 负责生成 Proposal,分发和提交事务。
-
Leader 选举机制
在以下两种场景中,ZooKeeper 会触发 Leader 选举:
-
集群首次启动
-
现有 Leader 崩溃或不可达
ZooKeeper 使用 ZAB 协议的恢复模式(ZAB Recovery Mode)进行 Leader 选举,确保系统始终拥有一个最新数据状态的 Leader 节点。
选举过程
-
所有节点启动时进入LOOKING(寻找) 状态,自我推荐为 Leader 候选人。
-
节点之间互相发送投票(vote),每次投票包含:
-
节点 ID
-
最新事务 ID(zxid)
-
-
投票策略如下:
-
优先选择zxid 最大的节点;
-
如果 zxid 相同,选择myid 最大的节点;
-
注意:zxid是由leader产生的,并且会广播给所有follower,但是每个follower的zxid可能是不一样的,因为节点日志更新是异步的:某个 Follower 网络慢、重启晚,可能还没收到最新几个 Proposal/Commit,它的 zxid 就会落后。
-
myid
是每个 ZooKeeper 节点的唯一标识编号,在集群部署中由管理员手动分配,通常是一个正整数。
-
-
一旦某个节点获得超过半数节点的认可(quorum),则被选为 Leader,其它节点状态切换为 FOLLOWING/OBSERVING。
-
选出的 Leader 会与所有节点进行数据对齐(同步日志)后,进入广播模式,正式对外服务。
Watch 机制(监听通知)
ZooKeeper 的 Watcher(监听器)机制是其最具特色的功能之一,为分布式系统提供了轻量级的事件通知能力,允许客户端在指定节点上注册监听,一旦节点状态发生变化,ZooKeeper 会异步通知客户端。Watch 机制非常适合用于配置变更通知、子节点变更感知等场景,是构建分布式协调系统的重要基础。
什么是 Watch 机制?
Watcher(监听器)是 ZooKeeper 提供的一种一次性、异步的回调通知机制。客户端可以通过 Watcher 订阅 ZooKeeper 上某个节点的变更事件。当节点发生变化时,ZooKeeper 会主动向客户端推送事件通知。
Watch 支持的事件类型
ZooKeeper Watcher 可以监听以下几类节点状态变化:
注意:
-
Watcher 监听不到子节点的内容变化,只能感知子节点的存在状态变化。
-
Watcher 不能递归监听,需要逐层手动注册。
Watch 触发流程
Client → ZooKeeper → 节点变化 → Watch 触发 → 客户端回调执行
-
客户端注册 Watcher
-
客户端通过 API(如
zoo_exists
、zoo_get
、zoo_get_children
)向 ZooKeeper 注册监听。 -
注册时需要传入回调函数,用于后续事件通知。
-
-
ZooKeeper 记录 Watcher
-
服务器会将 Watcher 暂存在内存中,等待节点状态变化。
-
-
节点发生变化
-
当节点被创建、删除、数据更新或子节点列表发生变化,ZooKeeper 会查找该节点上的所有 Watcher。
-
-
服务器推送事件通知
-
ZooKeeper 向所有注册了该节点 Watch 的客户端发送事件通知。
-
-
客户端执行回调函数
-
客户端收到通知后,立即调用注册的回调函数进行处理(如重新读取节点数据、刷新本地缓存等)。
-
数据持久化机制
ZooKeeper 采用内存 + 磁盘日志(事务日志和快照)的混合方式进行数据持久化,保证数据的高可用和恢复能力。
内存数据库(Data Tree)
-
ZooKeeper 在运行时会将所有的节点数据(znode)存储在内存中,形成一棵树状结构(Data Tree)。
-
所有读写操作都是基于这棵内存树进行的,读取速度非常快。
-
因为是内存数据,如果断电或服务重启,数据会丢失,所以需要持久化机制。
事务日志(Transaction Log)
-
ZooKeeper 会把所有写操作(创建、删除、修改节点等)以事务的形式顺序写入事务日志文件(
log.*
文件)。 -
事务日志是追加写的,不会修改已写入的内容,保证操作的顺序一致。
-
事务日志的写入保证了数据的持久化和顺序一致性,重启后可以通过日志回放恢复数据。
-
事务日志通常存储在 ZooKeeper 配置文件中
dataLogDir
指定的目录。
快照文件(Snapshot)
-
为了避免启动时回放所有事务日志导致恢复时间过长,ZooKeeper 会定期生成快照文件(
snapshot.*
)。 -
快照是对内存数据树当前状态的完整拷贝,存储在磁盘上(通常由
dataDir
指定目录)。 -
在重启时,ZooKeeper 会先加载最新的快照,再依次回放之后的事务日志,快速恢复数据状态。
-
快照生成频率可以通过配置参数
snapCount
控制(默认是 100000 条事务写入后生成快照)。
持久化流程总结