当前位置: 首页 > news >正文

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 的典型应用场景?

场景说明
服务注册与发现动态管理服务地址,客户端实时感知
分布式锁保证任务串行执行,防止并发冲突
配置中心多节点配置同步,实时生效
Master 选举高可用主备切换,节点自管理
分布式队列实现先进先出任务队列

ZooKeeper 已广泛应用于 HDFS、Kafka、HBase、Dubbo、gRPC 等分布式系统,是现代微服务架构的重要基础组件。

Zookeeper架构与部署

单机模式 vs 集群模式

ZooKeeper 支持单机模式和集群模式两种部署方式,适用于不同场景需求:

模式特点适用场景
单机模式无需选举,部署简单,服务单点;写入、读取请求由唯一节点处理开发环境、功能测试
集群模式主从架构,支持选举、支持容错;可水平扩展,具备高可用性生产环境

集群规模与容错能力

ZooKeeper 要求集群节点数量为奇数,以确保能够选出多数节点

节点数量可容忍宕机数最小生存节点数
1 台0 台1
3 台1 台2
5 台2 台3

最大容错数 = (n - 1) / 2,其中 n 是集群节点总数。

  • 生产环境建议至少 3 个节点,5 个更稳定。

  • 若需高并发读请求,可加入若干 Observer 节点,提升读性能但不影响一致性。

  • 所有集群节点必须配置一致的 zoo.cfg 配置文件中的 server 列表。

ZooKeeper 集群架构

ZooKeeper 集群使用经典的主从架构(Leader-Follower 架构),为了提高系统可扩展性和读性能,还引入了Observer(观察者)节点。整个集群以一个 Leader 为核心,配合多个 Follower 与 Observer 节点协同工作。

节点类型及职责划分

节点类型角色描述
Leader负责处理所有客户端写请求(事务性操作)、发起提议(Proposal)、收集投票并提交事务。
Follower参与投票选举 Leader,响应客户端读请求,将写请求转发给 Leader,并参与 Proposal 确认过程。
Observer只参与读操作,不参与 Leader 选举及 Proposal 投票过程,用于扩展系统读能力,不影响一致性。

ZooKeeper 的配置文件解析(zoo.cfg

ZooKeeper 的运行依赖一个名为 zoo.cfg 的配置文件,位于其安装目录下的 conf/ 目录中(通常路径为 conf/zoo.cfg),该文件控制着 ZooKeeper 的核心运行参数,如数据目录、端口号、会话超时时间,以及集群节点信息等。

配置文件的基本结构

zoo.cfg 是一个标准的键值对(key=value)格式的文本文件,内容结构简单,注释使用 # 开头。

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/var/lib/zookeeper/data
dataLogDir=/var/lib/zookeeper/log
clientPort=2181
server.1=192.168.1.1:2888:3888
server.2=192.168.1.2:2888:3888
server.3=192.168.1.3:2888:3888

关键配置项解释

基础配置项(单机或集群通用)

参数含义
tickTime心跳基准时间(单位:毫秒)。ZK 使用它作为会话超时、心跳等的时间单位。建议保持默认:2000ms。
initLimitFollower 与 Leader 初始连接时允许的最大心跳周期数量。限制了 Leader 等待 Follower 同步的时间,超过视为失败。
syncLimitLeader 与 Follower 之间同步数据的最长心跳周期数,超过则认为该 Follower 不可用。
dataDirZooKeeper 存储内存快照和事务日志的目录。目录下应有一个名为 myid 的文件(集群模式必备)。
dataLogDir事务日志的单独目录(可选)。若未设置,事务日志也写入 dataDir。分离可提高性能。
clientPortZooKeeper 对客户端开放的监听端口,默认 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 update
sudo apt install default-jdk
java -version

②下载安装 ZooKeeper

下载官方二进制包

Apache ZooKeeper

cd /opt
sudo wget https://downloads.apache.org/zookeeper/zookeeper-3.8.4/apache-zookeeper-3.8.4-bin.tar.gz
sudo tar -xzf apache-zookeeper-3.8.4-bin.tar.gz
sudo mv apache-zookeeper-3.8.4-bin zookeeper

③创建数据目录和日志目录

ZooKeeper 默认需要 dataDir 保存其事务日志和内存快照:

sudo mkdir -p /opt/zookeeper/data
sudo mkdir -p /opt/zookeeper/logs
sudo chown -R $USER:$USER /opt/zookeeper

④配置 ZooKeeper

进入 ZooKeeper 目录,复制配置模板:

cd /opt/zookeeper/conf
cp zoo_sample.cfg zoo.cfg

编辑 zoo.cfg 文件:

nano zoo.cfg

⑤启动 ZooKeeper 服务端

进入 ZooKeeper 根目录:

cd /opt/zookeeper
bin/zkServer.sh start

查看状态:

bin/zkServer.sh status

输出示例:

ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Mode: standalone

⑥验证连接

你可以用自带客户端连接:

bin/zkCli.sh -server 127.0.0.1:2181

连接后可以尝试:

create /testnode "hello"
get /testnode

常用命令汇总

服务端管理命令

命令说明
zkServer.sh start启动 ZooKeeper 服务
zkServer.sh stop停止 ZooKeeper 服务
zkServer.sh restart重启 ZooKeeper 服务
zkServer.sh status查看 ZooKeeper 当前状态

客户端启动命令

命令说明
zkCli.sh启动命令行客户端,默认连接 localhost:2181
zkCli.sh -server ip:port启动客户端并连接指定的 ZooKeeper 地址(远程/单节点)
zkCli.sh -server ip1:port1,ip2:port2,...启动客户端并连接多个节点地址(集群模式)

客户端交互命令(在 zkCli.sh 中使用)

命令说明
help查看所有可用命令
ls /path列出指定节点下的子节点
create <path> <data>创建一个节点并写入数据
get <path>获取指定节点的数据
set <path> <data>修改指定节点的数据
delete <path>删除指定节点
stat <path>查看节点状态信息(如版本、时间戳等元数据)
exists <path>判断节点是否存在
connect <host:port>动态连接到其他 ZooKeeper 服务地址
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。会话关闭,所有该会话创建的临时节点立即被删除。
客户端异常断连由于网络抖动或宕机导致连接断开,客户端未通知服务器。服务器开始计时,会话超时后关闭会话,删除对应临时节点。
客户端重连断线后客户端在会话超时前重新连接,恢复之前的会话状态。会话继续有效,临时节点依然存在,客户端可以继续操作。

会话与临时节点的关系:

临时节点是会话的产物,具有强绑定性:

  • 临时节点由某个会话创建。

  • 会话关闭(正常或异常超时),其对应的所有临时节点都会被 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_existszoo_getzoo_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 条事务写入后生成快照)。

持久化流程总结

操作处理流程
写请求(create/set/delete)1. 先写入事务日志(保证持久化) 2. 更新内存数据树
读请求直接读取内存数据树
定期快照定期将内存数据树写入快照文件,便于快速恢复
服务重启恢复1. 读取最新快照文件 2. 回放事务日志完成恢复
http://www.dtcms.com/a/268822.html

相关文章:

  • PostgreSQL性能优化实践指南:从原理到实战
  • 大语言模型(LLM)课程学习(Curriculum Learning)、数据课程(data curriculum)指南:从原理到实践
  • 知识竞赛答题pk小程序用户操作手册
  • Linux内核ext4 extent:解决大文件存储难题的关键
  • MybatisPlus(一)扩展功能
  • MS51224 一款 16 位、3MSPS、双通道、同步采样模数转换器(ADC)
  • LMH1219RTWR-富利威-3G/12G-SDI
  • 【mini-spring】【更新中】第一章 IOC与Bean源码及思路解析
  • 如何用 Mockito 玩转单元测试
  • 闲庭信步使用图像验证平台加速FPGA的开发:第三课——YCbCr转RGB的FPGA实现
  • 搜广推校招面经八十八
  • Linux批量执行工具脚本使用指南:一键运行多个release-dev.sh脚本
  • macOS运行python程序遇libiomp5.dylib库冲突错误解决方案
  • 【STM32】const 变量存储学习笔记
  • 【论文阅读】CogView: Mastering Text-to-Image Generation via Transformers
  • 文心一言4.5开源模型测评:ERNIE-4.5-0.3B超轻量模型部署指南
  • React19 新增Hooks:useOptimistic
  • 巧借东风:32位栈迁移破解ciscn_2019_es_2的空间困局
  • maven 发布到中央仓库-01-概览
  • 23、企业租赁管理(Rent)全流程指南:从资产盘活到价值最大化的数字化实践
  • Dify工作流实战:输入接口名,自动生成带源码的Markdown API文档(附完整Prompt)
  • Linux 文件系统与日志分析(补充)
  • 报错 400 和405解决方案
  • 海外短剧系统开发:PC端与H5端的全栈实践与深度解析
  • Day07- 管理并发和并行挑战:竞争条件和死锁
  • 在bash shell 函数传递数组的问题2
  • 【DeepSeek实战】17、MCP地图服务集成全景指南:高德、百度、腾讯三大平台接入实战
  • PCIE Ack/Nak机制详解
  • Unity 实现与 Ollama API 交互的实时流式响应处理
  • ES 压缩包安装