Zookeeper 的安装及使用
摘要
-
本文介绍 CentOS9 中 Zookeeper 的安装与使用。
-
本文使用的 Zookeeper 版本为 3.8.4。
Zookeeper 简介
-
ZooKeeper 是一个集中式服务,用于:
场景 | ZooKeeper 官方功能 | 主要节点类型 | 具体场景示例 |
---|---|---|---|
配置中心 (Config Center) | 维护配置信息 (Configuration Management) | 持久节点(Persistent) | 把数据库连接信息、系统参数等放在 ZooKeeper 里,动态更新,像 Apollo、Spring Cloud Config 一样。 |
注册中心 (Service Registry) | 提供命名服务 (Naming Service) | 临时节点(Ephemeral) | 服务实例启动时在 ZooKeeper 里注册自己的地址,客户端从 ZooKeeper 获取服务列表,类似于 Nacos、Eureka。 |
分布式锁 (Distributed Lock) | 分布式同步 (Distributed Synchronization) | 临时顺序节点(Ephemeral Sequential) | 用临时顺序节点实现分布式锁,保证只有一个实例在执行关键任务,典型应用是分布式定时任务调度。 |
消息队列 (Message Queue) | 集群管理服务 (Cluster Management) | 持久/临时节点 + Watch 机制 | 通过 Watch 机制监听 ZNode 变化,节点间用数据变更当“信号”传递消息,早期 Kafka 用过这种方式。 |
-
ZooKeeper 数据模型的结构与 Unix 文件系统很类似,整体上可以看作是一棵树,每个节点称做一个 ZNode。
-
不同于文件系统,每个节点都可以保存数据,每一个 ZNode 默认能够存储 1MB 的数据,每个 ZNode 都可以通过其路径唯一标识,每个节点都有一个版本(version),版本从0开始计数。
Zookeeper 安装
-
运行 Zookeeper 需要安装 JDK1.8+。我这里使用 OpenJDK11
1 | sudo mkdir -p /usr/local/jdk |
单机安装
-
下载 Zookeeper,目前最新的稳定版本为
3.8.4
1 | # 下载 |
-
修改配置文件
1 | cd zookeeper/conf |
zoo.cfg 参数说明
配置项 | 说明 | 默认值 | 单位 / 备注 |
---|---|---|---|
tickTime | ZooKeeper 时间配置中的基本单位 | 2000 | 毫秒 |
initLimit | follower 初始化连接到 leader 的最大时长,单位为 tickTime 倍数 | 10 | 10 × tickTime = 20000 ms |
syncLimit | follower 与 leader 数据同步的最大时长,单位为 tickTime 倍数 | 5 | 5 × tickTime = 10000 ms |
dataDir | 数据和日志存储目录(未指定 dataLogDir 时,日志也会保存在此目录) | /tmp/zookeeper | 目录路径 |
clientPort | 客户端连接 ZooKeeper 的端口号 | 2181 | 默认 2181 |
maxClientCnxns | 单个客户端最大并发连接数 | 60 | 超过限制后新连接会被拒绝 |
autopurge.snapRetainCount | 快照文件保留个数,超过数量的将会被清理 | 3 | 默认 3 |
autopurge.purgeInterval | 清理任务执行间隔时间,单位小时,0 表示不自动清理 | 1 | 1 小时 |
-
启动 zookeeper
1 | cd zookeeper |
集群安装
ZooKeeper 集群角色
1. Leader(领导者)
-
职责:
- 事务请求(写操作)的唯一调度者和处理者,保证集群事务处理的顺序性;
- 集群内部各个服务器的调度者;
- 对于
create
、setData
、delete
等写操作请求,统一转发给 Leader 处理; - Leader 负责决定编号、执行操作,这个过程称为 事务。
-
三台虚拟机 zoo.cfg 文件末尾添加配置,启动时会自动选举出 Leader 角色,则其余就是 Follower 角色。
1 | server.1=10.250.0.229:2888:3888 |
2. Follower(跟随者)
-
职责:
- 处理客户端非事务(读操作)请求(可以直接响应);
- 转发事务请求给 Leader;
- 参与集群 Leader 选举投票。
leader节点可以处理读写请求,follower只可以处理读请求。follower在接到写请求时会把写请求转发给leader来处理。
3. Observer(观察者)
-
职责:
- 对于非事务请求(读操作)可以独立处理;
- 对于事务请求会转发给 Leader 处理;
- 接收来自 Leader 的
inform
信息,更新本地存储; - 不参与提交和选举投票;
- 通常用于 提升集群非事务处理能力,不影响集群事务处理性能。
-
配置一个 ID 为 4 的观察者节点:
1 | server.4=10.250.0.56:2888:3888:observer |
集群搭建
-
环境准备:4台服务器,按照
单机安装
的方式准备好 Zookeeper 环境
1 | 10.250.0.229 |
-
zoo.cfg
文件末尾添加配置
1 | server.1=10.250.0.229:2888:3888 |
-
分别在
dataDir
目录下创建myid
文件,在文件中添加与 server 对应的编号(注意:上下不要有空行,左右不要有空格) -
分别启动 Zookeeper 服务器
1 | # 分别启动4个节点的zookeeper server |
集群最少节点要求和扩容规则
-
ZooKeeper 使用 多数派(quorum)机制 来保证数据一致性
1 | 1.集群总节点数 N |
-
集群扩容规则
1 | 1.节点总数必须是奇数 |
-
最少节点与容错能力表格
集群总节点数 N | 容忍宕机数 F | 可用 quorum 节点数 | 备注 |
---|---|---|---|
1 | 0 | 1 | 不推荐,无法容忍故障 |
2 | 0 | 2 | 不推荐,1 台宕机就不可用 |
3 | 1 | 2 | 最小可用生产集群 |
5 | 2 | 3 | 推荐生产集群规模 |
7 | 3 | 4 | 高可用大集群 |
9 | 4 | 5 | 更大集群,高容错 |
11 | 5 | 6 | 极高可用场景 |
ZooKeeper 默认端口说明
端口 | 用途 | 说明 |
---|---|---|
2181 | 客户端连接端口 | 客户端通过这个端口访问 ZooKeeper |
2888 | 集群内部通信 | follower 与 leader 之间同步数据 |
3888 | leader 选举端口 | 集群选举 leader 使用 |
8080 (可选) | admin/metrics web端口 | 如果开启了 adminServer |
1 | # 永久开启端口 |
客户端连接
-
命令行
1 | # 默认连接 127.0.0.1:2181 |
客户端命令简介:参考官网
命令 | 语法示例 | 功能描述 | 常用参数及说明 | 示例 |
---|---|---|---|---|
help | help |
显示所有操作命令 | 无 | help |
version | version |
查看客户端和服务器版本信息 | 无 | version |
connect | connect host:port |
连接到指定 ZooKeeper 服务器 | host:port : 服务器地址 |
connect 127.0.0.1:2181 |
close | close |
关闭当前会话 ,通过 connect 可重连 |
无 | close |
quit | quit |
退出客户端 | 无 | quit |
ls | ls [-s] [-w] [-R] path |
查看节点的子节点 | - -w : 监听子节点变化- -s : 显示节点状态信息- -R : 递归查看 |
ls -s -w /zk_test |
getAllChildrenNumber | getAllChildrenNumber path |
获取某节点所有子节点的总数 | 无 | getAllChildrenNumber /zk_test |
getEphemerals | getEphemerals path |
获取某路径下所有临时节点 | 无 | getEphemerals /zk_test |
create | create [-s] [-e] [-c] [-t ttl] path [data] [acl] |
创建节点 | - -s : 顺序节点- -e : 临时节点- -c : 容器节点- -t ttl : TTL节点,单位毫秒 |
create -e /zk_test_ephemeral "temp_data" |
get | get [-s] [-w] path |
获取节点数据信息 | - -s : 显示节点状态信息- -w : 监听节点变化 |
get -s -w /zk_test |
set | set [-s] [-v version] path data |
设置节点数据 | - -s : 显示节点状态信息- -v : 指定版本号 |
set /zk_test "new_data" |
stat | stat [-w] path |
查看节点状态信息 | - -w : 监听节点变化 |
stat -w /zk_test |
sync | sync path |
同步指定节点数据 | 无 | sync /zk_test |
delete | delete [-v version] path |
删除某一节点(无子节点) | - -v : 节点版本号 |
delete /zk_test |
deleteall | deleteall path |
递归删除某一节点及其子节点 | 无 | deleteall /zk_test |
getAcl | getAcl [-s] path |
获取节点访问控制信息 | - -s : 显示节点状态信息 |
getAcl /zk_test |
setAcl | setAcl [-s] [-v version] [-R] path acl |
设置节点访问控制列表 | - -s : 显示节点状态信息- -v : 指定版本号- -R : 递归设置 |
setAcl /zk_test world:anyone:r |
listquota | listquota path |
查看节点配额信息 | 无 | listquota /zk_test |
setquota | setquota [-n] [-b] val path |
对节点增加限制 | - -n : 子节点最大个数- -b : 数据值最大长度,-1 表示无限制 |
setquota -n 5 /zk_test |
delquota | delquota [-n | -b] path |
删除节点配额限制 | - -n : 删除子节点数限制- -b : 删除数据值大小限制 |
delquota -n /zk_test |
config | config |
查看服务器配置 | 无 | config |
whoami | whoami |
查看当前会话身份 | 无 | whoami |
-
GUI 工具
名称 | 类型 / 运行方式 | 优点 | 注意事项 |
---|---|---|---|
PrettyZoo | 桌面应用(JavaFX)(GitHub) | 支持 Mac/Windows/Linux,界面友好;支持节点创建/删除/更新/查询,ACL 管理,多 ZK 实例管理,SSH 隧道等功能。(GitHub) | 项目已经 archived,维护可能不活跃。最新版可能在兼容性或 Bug 修复方面不如活跃项目。也可能需要自己构建或调试。(GitHub) |
ZooNavigator | Web 界面 + 可 Docker 部署或本地启动(GitHub) | 功能丰富;支持多个 Zookeeper 版本(如 3.5.x ~ 3.9.x);浏览 / 编辑 /搜索节点;导入导出配置;支持浏览器访问,无需本地 heavy GUI。(GitHub) | 因为 Web 应用,可能对浏览器安全策略与网络延迟敏感;需要部署自己版本或 Docker;如果要求本地脱机操作时,有些功能可能稍不如桌面应用。 |
ZooKeeper Assistant | 桌面/管理员面板类型(支持监控界面等)(DEV Community) | 除了浏览节点树以外,还提供健康状态监控(延迟、请求数等)、不同数据格式支持(JSON/XML 等)、导入/导出节点数据、命令行操作集成。(DEV Community) | 有些功能可能在 Mac 上兼容性或视觉体验需要调试;具体版本支持情况要看最近更新。某些监控界面可能依赖于 ZK 的指标或插件。 |
Zookeeper 节点类型
节点类型 | 生命周期说明 | 创建命令示例 | 特点说明 |
---|---|---|---|
持久节点 (Persistent) | 节点一直存在,除非手动删除,即使客户端会话关闭,节点也不会消失 | create /locks |
适合存储配置信息、元数据等持久数据 |
临时节点 (Ephemeral) | 客户端会话关闭(异常或超时)时,节点自动被删除 | create -e /locks/DBLock |
常用于分布式锁、临时会话数据 |
有序节点 (Sequential) | 在持久或临时节点基础上,增加有序编号,ZooKeeper 自动在节点名后加递增序号 | create -e -s /jobs/job |
常用于分布式锁、队列等需要顺序的场景 |
容器节点 (Container) | V3.5.3+,当容器节点下的最后一个子节点被删除后,容器节点也会自动删除 | create -c /work |
适合分布式任务临时目录、动态数据目录 |
TTL 节点 (TTL) | 在指定 TTL 时间内未修改且无子节点,节点会被自动删除(需开启 extendedTypesEnabled=true 配置) |
create -t 3000 /ttl_node |
适合临时缓存、临时状态数据,过期自动清理 |
-
注意
- 同一级节点 key 名称是唯一的
- 创建节点时,必须要带上全路径
-
节点状态信息
1 | [zk: localhost:2181(CONNECTED) 16] stat /test |
Zookeeper 监听机制
-
watch机制,顾名思义是一个监听机制。Zookeeper中的watch机制,必须客户端先去服务端注册监听,这样事件发生时才会触发监听,通知给客户端。
-
监听的对象是事件,支持的事件类型如下:
1 | - None: 连接建立事件 |
-
监听特性
特性 | 说明 |
---|---|
一次性触发 | Watch 是一次性的,一旦被触发就会被移除。再次使用时需要重新注册。 |
客户端顺序回调 | Watch 回调是顺序串行执行的,客户端只有在回调完成后才能看到最新的数据状态。 |
轻量级 | Watcher 回调逻辑不应过多,以免阻塞或影响其他 Watch 的执行。 |
最小通信单位 | WatchEvent 是最小的通信单位,只包含通知状态、事件类型和节点路径,不包含节点数据变化前后的具体内容。 |
时效性 | Watcher 仅在当前 Session 完全失效时才无效。如果 Session 快速重连成功,Watcher 依然有效,可继续接收通知。 |
-
可以开启监听的命令
1 | #监听节点数据的变化 |
永久性 Watch
-
在被触发之后,仍然保留,可以继续监听ZNode上的变更,是Zookeeper 3.6.0版本新增的功能
-
创建监听
1 | addWatch [-m mode] path |
-
删除监听
1 | # 普通一次性 Watch 不需要手动删除,触发后会自动移除;removewatches 主要用于持久 Watch(persistent watch)。 |
监听器应用场景
类型 | 特点 | 应用场景举例 | 适合的节点类型 |
---|---|---|---|
临时监听(一次性 Watch) | - 触发一次后自动移除 - 客户端需手动重新注册 - 轻量级,适合单次通知 |
1. 配置中心:配置变化时通知客户端,客户端收到通知后重新拉取最新配置 2. 分布式锁:节点删除(锁释放)后通知等待的客户端重新竞争锁 3. 主从选举:主节点宕机后,其他节点收到通知重新选主 |
持久节点(Persistent) 临时节点(Ephemeral,用于锁和选主) |
永久监听(Persistent Watch) | - 注册后持续有效,直到客户端主动移除 - 支持子节点变化、数据变化的长期监听 |
1. 服务发现:客户端长期监听服务节点变化,节点上线/下线时自动更新本地服务列表 2. 监控告警:监控重要节点状态,节点数据变化或被删除时自动触发告警 3. 分布式缓存:缓存节点变化时,通知客户端刷新缓存 |
持久节点(Persistent) |
ACL权限控制
-
ZooKeeper 默认情况下,所有节点的权限都是
OPEN_ACL_UNSAFE
,任何客户端都可以读写任意节点数据。 -
生产环境中,通常需要限制对节点的访问权限,即
ACL
权限控制。 -
ZooKeeper 里的 ACL(Access Control List,访问控制列表) 主要用于控制 谁可以对某个节点做什么操作,它是 ZooKeeper 提供的安全机制之一。
ACL 的作用
-
限制访问:只允许授权用户或客户端对指定节点进行读、写、删除等操作。
-
防止误操作:保护重要节点不被未授权的客户端修改或删除。
-
安全隔离:不同的应用或团队可以在同一 ZooKeeper 集群里安全共存。
ACL 的组成
-
zookeeper 的 acl 通过
scheme:id:permissions
来构成权限列表。- scheme:授权的模式,代表采用的某种权限机制,包括 world、auth、digest、ip、super 几种。
- id:授权对象,代表允许访问的用户。如果我们选择采用 IP 方式,使用的授权对象可以是一个 IP 地址或 IP 地址段;而如果使用 Digest 或 Super 方式,则对应于一个用户名。如果是 World 模式,是授权系统中所有的用户。
- permissions:授权的权限,权限组合字符串,由 cdrwa 组成,其中每个字母代表支持不同权限, 创建权限 create©、删除权限 delete(d)、读权限 read®、写权限 write(w)、管理权限admin(a)。
常见的 scheme 类型
Scheme | 说明 | 示例 |
---|---|---|
world |
开放给所有用户,仅可设置为 anyone 代表所有客户端 |
world:anyone:r |
auth |
已通过 addauth 添加认证的客户端 |
auth:user1:rw |
digest |
用户名+密码认证(常用),user:pwd 需要加密存储 |
digest:user1:password:rw |
ip |
基于 IP 地址控制访问 | ip:192.168.1.10:r |
super |
超级用户,拥有所有权限 | super:admin:secret |
权限类型
权限字符 | 权限名称 | 允许的操作/命令示例 | 说明 |
---|---|---|---|
r |
读取(Read) | get /node ls /node getAcl /node |
允许读取节点数据和子节点列表 |
w |
写入(Write) | set /node data |
允许修改节点数据 |
c |
创建(Create) | create /node/sub "data" |
允许在当前节点下创建子节点 |
d |
删除(Delete) | delete /node/sub |
允许删除当前节点的子节点 |
a |
管理(Admin) | setAcl /node acl |
允许修改 ACL 权限 |
典型应用场景
认证方式(scheme) | 权限类型(permissions) | 典型 ACL 配置示例 | 应用场景 | 特点说明 |
---|---|---|---|---|
world | r (只读) |
world:anyone:r |
公共配置节点,所有客户端都可读取 | 简单、无认证,适合对安全性要求不高的只读场景 |
auth | r,w,c,d,a (可组合) |
auth:user:rwcd |
内部应用共享节点,需客户端认证 | 需先 addauth digest user1:password 添加认证,适合多客户端共享 |
digest(常用) | r,w,c,d,a (可组合) |
digest:user:secret:crwda |
高安全节点,配置中心,分布式锁 | 用户名+密码认证,需加密存储密码,灵活安全 |
ip | r,w,c,d,a (可组合) |
ip:192.168.1.100:r |
基于 IP 限制访问的场景 | 快速控制某些固定 IP 可访问,适合内部网络应用 |
ACL 相关命令
命令 | 语法 | 功能说明 | 示例 |
---|---|---|---|
getAcl | getAcl path |
读取指定节点的 ACL | getAcl /my_node |
setAcl | setAcl path acl |
设置指定节点的 ACL | setAcl /my_node world:anyone:crdwa |
create | create path data [acl] |
创建节点时指定 ACL | create /secure_node "secret_data" digest:user1:pwd:crwa |
addAuth | addauth scheme auth |
添加认证用户(类似登录) | addauth digest user1:password |
deleteAcl(不存在) | setAcl path world:anyone: |
删除节点 ACL(设为空或全开放) | setAcl /my_node world:anyone: |
auth
与 digest
的区别
-
使用
auth
时,需先addauth digest user1:password
添加认证,setAcl
时,使用auth:user1:rw
,这里是为已经登录的用户设置节点权限,所以不需要设置密码 -
使用
digest
时,无需进行登录认证,所以需要指定密码,即setAcl
时,使用digest:user1:password:rw
-
digest
的密码是经过加密的,所以不能直接使用明文密码
1 | # 加密密码 |
-
无论使用
digest
还是auth
,在需要访问节点前,都需要先登录。
super
超级管理员
-
拥有全部节点的所有权限:
crwda
-
设置超级管理员
1 | # 加密密码,用户和密码可以随意设置 |
-
重新启动服务后登录客户端进行测试
1 | # 创建节点并设置权限,这里将节点授权给用户user |
4字母命令
什么是 4 字母命令
?
-
ZooKeeper 提供了一组简短的
4个字母的管理命令
(Four Letter Words Commands, 4lw),可以通过 TCP 连接 ZooKeeper 端口(默认 2181)发送这些命令,快速查看或管理 ZooKeeper 状态。 -
常用的
4字母命令
命令 | 引入版本 | 功能描述 | 示例 |
---|---|---|---|
conf |
3.3.0 | 打印服务相关配置的详细信息 | echo conf | nc 127.0.0.1 2181 |
cons |
3.3.0 | 列出所有连接到该服务器的客户端连接/会话详细信息,包括接收/发送的包数量、会话ID、操作延迟、最后操作执行时间等 | echo cons | nc 127.0.0.1 2181 |
crst |
3.3.0 | 重置所有连接的连接和会话统计信息 | echo crst | nc 127.0.0.1 2181 |
dump |
- | 列出重要的会话和临时节点信息,仅在 Leader 节点上有效 | echo dump | nc 127.0.0.1 2181 |
envi |
- | 打印服务环境的详细信息 | echo envi | nc 127.0.0.1 2181 |
reqs |
- | 列出未经处理的请求 | echo reqs | nc 127.0.0.1 2181 |
ruok |
- | 测试服务是否处于正常状态;正常返回 imok |
echo ruok | nc 127.0.0.1 2181 |
stat |
- | 输出关于性能和客户端连接的列表信息 | echo stat | nc 127.0.0.1 2181 |
srst |
- | 重置服务器统计信息 | echo srst | nc 127.0.0.1 2181 |
srvr |
3.3.0 | 列出连接服务器的详细信息 | echo srvr | nc 127.0.0.1 2181 |
wchs |
3.3.0 | 列出服务器 Watch 的详细信息 | echo wchs | nc 127.0.0.1 2181 |
wchc |
3.3.0 | 通过会话列出服务器 Watch 的详细信息,输出与 Watch 相关的会话列表 | echo wchc | nc 127.0.0.1 2181 |
wchp |
3.3.0 | 通过路径列出服务器 Watch 的详细信息,输出与会话相关的路径 | echo wchp | nc 127.0.0.1 2181 |
mntr |
3.4.0 | 输出可用于检测集群健康状态的关键指标变量列表 | echo mntr | nc 127.0.0.1 2181 |
开启 4字母命令
-
在 ZooKeeper 3.5.0 及之后的版本,4lw 命令默认是禁用的,必须在配置文件(zoo.cfg)中显式开启。
1 | # 表示允许所有 4lw 命令都能用(风险最大) |
-
使用方法
1 | # 如果没有安装 nc,可以使用 yum 安装 |
Zookeeper Java Client
-
项目示例:Github地址,单元测试。
Zookeeper 官方Java客户端
-
ZooKeeper官方的客户端API提供了基本的操作。例如,创建会话、创建节点、读取节点、更新数据、删除节点和检查节点是否存在等。不过,对于实际开发来说,ZooKeeper官方API有一些不足之处,具体如下:
- ZooKeeper的Watcher监测是一次性的,每次触发之后都需要重新进行注册。
- 会话超时之后没有实现重连机制。
- 异常处理烦琐,ZooKeeper提供了很多异常,对于开发人员来说可能根本不知道应该如何处理这些抛出的异常。
- 仅提供了简单的byte[]数组类型的接口,没有提供Java POJO级别的序列化数据处理接口。
- 创建节点时如果抛出异常,需要自行检查节点是否存在。
- 无法实现级联删除。
- 总之,ZooKeeper官方API功能比较简单,在实际开发过程中比较笨重,一般不推荐使用。
-
项目引入依赖时,最好保持与服务端版本一致,否则可能会有一些兼容性的问题
1 | <!-- zookeeper client --> |
Zookeeper 第三方Java客户端 Curator
-
Curator是Netflix公司开源的一套ZooKeeper客户端框架,和ZkClient一样它解决了非常底层的细节开发工作,包括连接、重连、反复注册Watcher的问题以及NodeExistsException异常等。
-
Curator是Apache基金会的顶级项目之一,Curator具有更加完善的文档,另外还提供了一套易用性和可读性更强的Fluent风格的客户端API框架。
-
Curator还为ZooKeeper客户端框架提供了一些比较普遍的、开箱即用的、分布式开发用的解决方案,例如Recipe、共享锁服务、Master选举机制和分布式计算器等,帮助开发者避免了“重复造轮子”的无效开发工作。
-
在实际的开发场景中,使用Curator客户端就足以应付日常的ZooKeeper集群操作的需求。
-
引入依赖说明:
模块 | 依赖关系 | 功能定位 | 典型功能举例 | 常用场景 |
---|---|---|---|---|
curator-client | 依赖 zookeeper | 连接管理、重试策略、底层 API | 连接会话管理、RetryPolicy | 需要最轻量的 ZooKeeper 客户端 |
curator-framework | 依赖 curator-client | 高层 API 封装,简化 ZK 操作 | 创建节点、Watcher 管理、自动重连 | 通用 ZooKeeper 客户端开发 |
curator-recipes | 依赖 curator-framework → curator-client | 分布式模式现成实现 | 分布式锁、Leader 选举、队列、Barrier | 直接用分布式工具,无需自己实现 |
使用建议
-
如果你只想轻量访问 ZooKeeper →
curator-client
就够了,但几乎没人单独用。 -
如果你想方便操作 ZooKeeper API →
curator-framework
,大部分情况都适用。 -
如果你想用分布式锁、选举、Barrier →
curator-recipes
(它会自动引入前两个)。
1 | <!-- zookeeper client --> |