拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ZooKeeper集群搭建完整指南:从配置到故障排查

ZooKeeper集群搭建完整指南:从配置到故障排查

先说个我自己当年的经历:第一次搭ZooKeeper集群时,照着教程准备三台机器、三份配置,依次启动之后执行zkServer.sh status,三台全是follower。我一度以为配置错了,反复删 data 目录重来,最后才明白:当时只有一个节点真正组网成功,其余节点根本没找到彼此——这种“进程活着、状态也能查,但集群其实没形成”的情况,是 ZooKeeper 集群新手最容易踩的坑。

这篇博文就把整套 ZooKeeper 集群搭建步骤完整拆开讲。内容面向需要搭 Hadoop HA、Kafka、Spark 等大数据生态组件,或者任何需要分布式协调服务的开发者与运维同学。我会把节点规划、核心配置文件解析、初始化动作、启动验证方法、高频故障排查思路,以及后续扩容运维的注意点一次说清楚。每条配置参数、每个启动命令背后为什么这么做,我也会尽量说明白,而不是丢一份配置让你“照着抄就完事”。

1. 动手之前先解决三件事:奇数节点、时钟同步与hostname

1.1 为什么说三节点起步、五节点更好,奇数节点的道理在哪

ZooKeeper 集群最经典的问题就是:我该搭几台?答案是至少 3 台,生产环境建议 5 台,而且一定要奇数。原因不在于“玄学”,而在于它的选举机制基于多数派(majority quorum)原则。

简单说,ZooKeeper 内部选 Leader 时,一个节点要成为 Leader,必须获得超过半数的投票。比如 3 节点集群,至少需要 2 票;5 节点集群至少需要 3 票。这意味着:

总节点数可容忍宕机数说明
10单点,不叫集群
20任意一台宕机都会导致无法形成多数派,白费资源
31最常见的起步配置
41只能容忍 1 台宕机,和 3 节点一样,但多花一台机器
52生产环境常见配置
73大型集群或跨机房部署时考虑

所以你会发现:4 节点和 3 节点能容忍的故障数量一样,但成本和维护复杂度更高。奇数节点不是为了让“少数服从多数”时票数好看,而是保证在故障场景下的可用性上限最高。

另外还要知道一个角色:Observer。Observer 不参与投票,只负责同步 Leader 数据和响应读请求。如果你需要扩展读能力但又不想增加选举节点的数量(避免投票变慢),就可以用 Observer。它特别适合跨机房只读场景。搭建时暂时用不到,但架构评审时可以提一嘴。

1.2 三台机器的基本规格与网络要求

ZooKeeper 本身很轻量,不是吃 CPU 和内存的服务,但它的性能非常依赖磁盘和网络。官方设计目标就是低延迟、高可靠,所以以下几点在规划阶段就要定下来:

  • CPU:4 核起步,足够了
  • 内存:4G 起步,建议 8G。注意别给太大堆内存,我在后面 JVM 部分会详细说
  • 磁盘:普通 SSD 就行,但尽量给独立的数据盘,不要把系统盘和 ZooKeeper 数据目录塞在一起
  • 网络:千兆内网即可,但节点之间的延迟要稳定,跨机房场景建议把机房间专线质量纳入评估

系统方面,CentOS 7.x、Ubuntu 20.04/22.04 都行。JDK 建议 1.8 或 11,ZooKeeper 3.5 到 3.9 都能跑。不要用太老旧的 JDK 版本,比如 JDK 6,新版本已经明确不支持。

1.3 hostname 与 /etc/hosts:最容易偷懒但最容易埋雷的一步

很多教程会说“三台机器分别配好 hostname”,但实际执行时经常有人忽略hosts文件。ZooKeeper 配置文件里写的是主机名,如果节点之间解析不了对方的主机名,启动后大量报错会指向地址无法解析。

我的建议是,集群内所有节点都在/etc/hosts里互相写全量记录。以三节点为例:

192.168.10.11 node01 192.168.10.12 node02 192.168.10.13 node03

三台机器都要写这个完整清单,不要只写自己的。因为节点之间要互相访问,不能只让自己能解析自己。配完后用ping node02从 node01 测一下,三个方向都通再继续。

另外,各节点的/etc/hostname要分别改成对应名字,改完重启或者执行hostnamectl set-hostname node01让它立即生效。

1.4 系统时钟同步与防火墙预检查

ZooKeeper 对时间同步程度比较敏感。节点之间时间差太大会导致消息乱序、会话超时判断出现偏差,尤其在高负载和故障切换时容易引发奇怪问题。生产环境一定要做 NTP 或 chrony 同步,建议指向公司内网的 NTP 服务器;如果只是测试环境,至少也要保证各节点时间误差控制在秒级以内。

防火墙和端口方面,ZooKeeper 三个端口需要提前知道:

端口用途
2181客户端连接端口
2888Follower/Observer 与 Leader 之间的数据同步端口
3888集群选举端口

如果测试环境懒得搞防火墙,可以直接systemctl stop firewalld并禁用开机自启。生产环境则要在安全组或本机防火墙里放行这三个端口,并且要允许三台机器之间的互相访问。我见过不少案例,2181 对外开放了,但 2888/3888 没放行,结果客户端能连上,集群内部却一直选不出 Leader。

2. zoo.cfg:核心参数说明白,配置才不会云里雾里

2.1 先给一份可直接使用的完整配置

进入正题。假设 ZooKeeper 已经解压到/opt/zookeeper-3.9.2,并且做了软链/opt/zookeeper指向该目录。配置文件位置是conf/zoo.cfg,默认没有这个文件,需要从zoo_sample.cfg复制一份再改。

一份三节点集群的最小可用配置如下:

tickTime=2000 initLimit=10 syncLimit=5 dataDir=/data/zookeeper/data clientPort=2181 server.1=node01:2888:3888 server.2=node02:2888:3888 server.3=node03:2888:3888 autopurge.snapRetainCount=3 autopurge.purgeInterval=1 maxClientCnxns=60 admin.enableServer=true

这个配置看起来简单,但每行背后都有讲究,下面拆开讲。

2.2 tickTime、initLimit、syncLimit:三个时间参数决定了集群的“心跳节奏”

tickTime是 ZooKeeper 使用的基本时间单位,单位是毫秒。默认 2000,也就是 2 秒。会话超时时间、节点之间心跳间隔、选举超时判断都基于这个单位。你可以把它理解成整个集群的“心跳节拍器”。

initLimit表示 Follower 启动后,从开始连接 Leader 到完成数据同步所允许的最大时间,单位是 tickTime 的倍数。initLimit=10意味着最长允许 10 * 2000 = 20 秒。如果集群数据量很大,或者网络比较慢,同步时间可能超过这个值,需要适当调大。三节点清一色全新安装时数据量很小,10 足够了。

syncLimit表示 Follower 与 Leader 之间正常心跳同步的最大间隔,单位同样是 tickTime 的倍数。syncLimit=5意味着最多允许 5 * 2000 = 10 秒没有心跳响应,超过这个时间 Leader 会认为 Follower 挂了,或者 Follower 认为 Leader 失联,进而触发新一轮选举。这个值不用调太大,5 是常见选择。

这三个参数是 ZooKeeper 集群运行节奏的基础,不要盲目改大。值过大意味着故障发现变慢,选主时间变长,对上层业务的影响会更明显;值过小又容易因为 GC 抖动或网络瞬时延迟造成误判。

2.3 dataDir 和 dataLogDir:数据放哪里,可能是性能瓶颈的第一来源

dataDir是 ZooKeeper 存储内存数据库快照(snapshot)和事务日志的目录,同时也是存放 myid 文件的目录。注意,这里其实包含了两种性质完全不同的文件:快照是某个时刻内存数据全量拷贝,事务日志是每次写操作的增量记录。

生产环境建议增加dataLogDir,把事务日志单独放到独立磁盘目录。因为 ZooKeeper 每次写请求都要落事务日志,写完才返回。如果数据日志和系统日志或快照混在同一块盘上,磁盘 IO 竞争会直接影响写延迟。事务日志用一块独立的 SSD,能明显提升性能。

dataDir=/data/zookeeper/data dataLogDir=/data/zookeeper/datalog

还需要注意,如果指定了dataLogDir,myid 文件还是放在dataDir里,不会挪走。

2.4 server.N 配置行:2888 和 3888 到底分别是什么端口

server.1=node01:2888:3888这行的格式是server.节点编号=主机名:数据同步端口:选举端口。

这里的编号要和每台机器 dataDir 下的 myid 文件内容严格对应。举个例子,node01 的 myid 文件内容必须是 1,node02 必须是 2,node03 必须是 3。集群是通过这个编号识别身份的,写错或重复都不行。

第一个端口 2888 是 Follower 连接 Leader、进行数据同步的端口;第二个端口 3888 是集群在选举阶段各节点互相通信的端口。有些人会记反,但记住一条主线就行:数据走 2888,选主走 3888。

如果服务器有多块网卡,或者存在多 IP 情况,默认监听可能只会绑定到某个网卡上。此时需要根据实际网络环境设置quorumListenOnAllIPs=true,否则集群节点之间可能无法互相访问选举端口。单网卡的常规场景不用管。

2.5 几个容易被忽略但值得写的附加参数

autopurge.snapRetainCount=3和autopurge.purgeInterval=1是配套的自动清理策略。前者表示保留最近多少个快照,后者表示每隔多少小时执行一次清理。如果不设置,长期运行的 ZooKeeper 会在 dataDir 下积累大量快照和日志文件,把磁盘撑爆。这个参数在 3.4.0 之后引入,建议测试环境就顺手配上。

maxClientCnxns=60表示限制单个 IP 对 2181 端口的最大并发连接数。默认是 60,如果业务方某个服务大量创建客户端连接,容易被误杀,需要根据实际情况调大。0 表示不限制,但生产环境不建议取消限制。

admin.enableServer=true是 3.5 之后引入的参数,会启动一个内嵌的管理服务,默认监听 8080 端口,用来提供简单的健康检查和四字命令的 HTTP 接口。如果你不需要,可以显式设为 false;不设置时默认是 true。注意这个端口如果和业务端口冲突,也需要调整或关闭。

3. 逐台初始化节点:myid、JVM参数与启动顺序

3.1 myid 文件的创建:一个数字就是一台机器的身份ID

在所有配置文件分发到三台机器之前,先单独做一件事:在每台机器的 dataDir 目录下写入 myid 文件。命令非常简单:

# node01 上执行 mkdir -p /data/zookeeper/data echo 1 > /data/zookeeper/data/myid # node02 上执行 mkdir -p /data/zookeeper/data echo 2 > /data/zookeeper/data/myid # node03 上执行 mkdir -p /data/zookeeper/data/myid

注意,每台机器的 myid 必须唯一,且必须和 zoo.cfg 里的server.N编号一致。这里最容易出的问题不是写错数字,而是有人直接复制整台机器的 data 目录到其他节点,导致所有节点 myid 都是 1,集群启动后号错乱,现象极其隐蔽。

还有一个细节:如果之后想把某台节点踢出集群,只改 zoo.cfg 还不够,还要处理对应编号和 myid 的关系,否则残留节点可能带病参与选举。

3.2 JVM 堆内存建议:不是越大越好,超过 4G 反而容易出问题

ZooKeeper 是一个内存型协调服务,内存中保存整个数据树模型。但它并不需要存海量业务数据,正常一个集群所有配置节点加起来也就几百 MB 到几个 G,因此 JVM 堆内存不需要给得很大。

如果堆内存给到 8G、16G,发生 Full GC 时停顿时间会明显拉长,节点在一段时间内无法响应 Leader 的心跳和客户端请求,反而会被集群判定为超时,引发不必要的会话过期和重新选举。我个人的经验是,默认 1G 起步,2G 到 4G 足够绝大多数场景使用。

修改 JVM 参数的标准位置有两个:较新版本可以在conf/zookeeper-env.sh中设置JVMFLAGS,或者直接在bin/zkServer.sh中找ZOO_MAIN相关区域调整。我习惯用zookeeper-env.sh,因为它不影响启动脚本的其他行为:

export ZOO_LOG_DIR=/var/log/zookeeper export JVMFLAGS="-Xms2g -Xmx2g"

ZOO_LOG_DIR用来指定日志输出目录。如果这个目录不存在,需要先创建。日志文件默认叫zookeeper.out,排错时最常翻的就是它。

3.3 配置文件分发:scp 只发配置,别整个目录拷贝

三台机器解压完 ZooKeeper 后,最好先在 node01 上把zoo.cfg彻底改好,再分发给其他节点:

scp /opt/zookeeper/conf/zoo.cfg node02:/opt/zookeeper/conf/zoo.cfg scp /opt/zookeeper/conf/zoo.cfg node03:/opt/zookeeper/conf/zoo.cfg

分发配置时可以顺带检查软链是否已创建。很多教程喜欢把解压包直接命名为/opt/zookeeper,以后升级就要改一堆路径;我更习惯用/opt/zookeeper-版本号加/opt/zookeeper软链方式,升级时只需要切软链。

千万别做的一步:把 node01 的整个 data 目录 scp 到 node02 和 node03。dataDir 里不仅有 myid,还有快照文件和事务日志,这些是节点本地的数据状态,一旦复制过去,新节点会以为自己的历史数据是完整的,启动后可能加载出脏数据;同时 myid 也会冲突。所以每台节点的 dataDir 必须全新创建,只写入自己的 myid 文件。

3.4 启动顺序:第一台启动报一堆连接错误是正常的

三节点都初始化完成后,启动顺序其实没有强制要求,但我建议按照编号顺序依次启动,方便观察。

# 每台节点分别执行 /opt/zookeeper/bin/zkServer.sh start

重点来了:第一台节点启动时,它会尝试连接其他节点,但其他节点还没启动,所以日志中会出现大量Cannot open channel to X at election address之类的连接失败信息。这并不代表配置错误,而是单节点无法达到多数派,它只能干等。

这也是为什么新手会得到“三台都是 follower”的原因之一:第一台启动时孤零零没法定 Leader,等第二台启动、第三台还没起来时,可能第二台发现了第一台但依然凑不齐多数派。只有当第三台启动、达到多数派条件后,集群才会选出 Leader。此时再执行zkServer.sh status,才会看到一台 Leader、两台 Follower 的正常局面。

如果想在前台观察启动过程中的详细日志,可以用zkServer.sh start-foreground。这是排查启动问题的最佳方式,因为它会把整个启动过程直接打到终端,任何配置错误都会明白显示出来。调试完再切回start方式即可。

4. 启动后如何确认集群真的健康

4.1 status 输出怎么看:一台 Leader、两台 Follower 才是正常

集群全部启动后,分别在三台节点上执行:

/opt/zookeeper/bin/zkServer.sh status

正常结果应该是:一台节点显示Mode: leader,另外两台显示Mode: follower。只有 leader/follower 三台都输出正常,才说明多数派就绪,集群真正工作。

如果某台节点显示Mode: standalone,几乎可以断定这台节点没有和另外两台组成集群,而是自己以单机模式跑起来了。常见原因包括:zoo.cfg 中没有配置任何server.N行、配置文件没同步到其他节点、网络端口不通导致无法互相发现。

4.2 四字命令:比 status 更细粒度的健康体检

ZooKeeper 提供了一套四字命令,通过向 2181 端口发送简单字符串来查询状态。常见的有:

echo stat | nc 127.0.0.1 2181 echo srvr | nc 127.0.0.1 2181 echo ruok | nc 127.0.0.1 2181 echo mntr | nc 127.0.0.1 2181

mntr输出的是监控指标,信息量最大,包括当前节点角色、节点数、接收和发送的数据包数量、延迟时间等。生产环境的 ZooKeeper 监控脚本基本都是基于mntr采集的。

需要注意,ZooKeeper 3.5 之后默认启用了四字命令白名单机制,未在白名单内的命令会返回command not known或者直接不返回。如果发现stat等命令无效,需要在 zoo.cfg 里加一行:

4lw.commands.whitelist=stat, ruok, conf, srvr, mntr

在非安全的内网环境,不要图省事配置成4lw.commands.whitelist=*,因为有些命令会导致性能开销,开放越少越好。

4.3 客户端读写验证:集群状态最后还是要用数据说话

状态检查只是看了心跳,真正要确认集群数据一致性和读写能力,还得通过客户端实际操作一下。

用一个节点连集群:

/opt/zookeeper/bin/zkCli.sh -server node01:2181,node02:2181,node03:2181

进入客户端后执行:

create /test_cluster ok get /test_cluster

再换一个节点连接,执行同样的get命令,应该也能读到相同数据。这说明数据已经通过 Leader 同步到了各节点。

如果想更严谨地验证故障转移能力,可以做一次受控演练。找到 Leader 节点,把它停掉:

/opt/zookeeper/bin/zkServer.sh stop

等待几秒后,在剩余两个节点上分别执行 status,应该能看到其中一个变成了 leader。再把停掉的节点启动,它应该会自动加入集群并变成 follower。这一步如果顺利跑通,说明这个集群真正具备故障转移能力,而不是“表面健康,实际单点”。

4.4 验证阶段最容易忽略的细节

第一次做客户端验证时,建议用连接串的方式而不是只连单个 IP。zkCli.sh -server node1:2181这种方式虽然方便,但一旦连的节点地址写错,客户端会一直无法连接,你会误以为是集群问题。用完整连接串能验证三个节点是否都可达。

另外,客户端连接时的sessionTimeout参数决定了会话的有效期。如果设置过短(比如 5 秒),而节点刚好有轻微 GC 或者网络抖动,session 很容易过期,临时节点会全部被删除。生产环境建议根据业务实际情况设置,不要盲目追求短超时。

5. 搭建过程中最常见的高频问题与排查链路

5.1 “Cannot open channel to X at election address”:先从选举端口查起

这是搭建期出现频率最高的报错。如果你在日志中看到类似:

Cannot open channel to 2 at election address /192.168.10.12:3888

说明当前节点无法连接到编号为 2 的节点的 3888 端口,而这个端口恰好是选举端口,不是客户端端口。很多人查了半天 2181 端口通不通,完全找错了方向。

排查链路如下:

  1. 确认/etc/hosts中 hostname 与 IP 的映射是否正确,ping node02能不能通
  2. 确认目标机器的 3888 端口是否监听:netstat -lnp | grep 3888
  3. 从当前节点测试到目标端口是否可达:telnet node02 3888
  4. 检查防火墙是否放行了 2888 和 3888 这两个端口

注意,ping通只能说明 ICMP 通,不能代表 TCP 端口通。一定要做 telnet 或nc -vz级别的验证。

5.2 所有节点启动后 status 全是 follower 或者全是 leader-less

如果你看到三个节点都显示follower,或者更奇怪的现象——每个节点查 status 时看到自己都不是 leader,但也没有明显报错,优先考虑以下原因:

  • 配置文件没有同步到所有节点,或者其中一台用的还是旧配置
  • myid 文件内容重复,比如两台都是 1
  • 数据目录里残留着之前测试的数据,旧日志写入导致初始化异常
  • 各节点时间偏差太大,选举过程无法正常完成

我的建议是,在所有节点执行以下命令,把实际生效的配置打出来对比:

echo conf | nc 127.0.0.1 2181

这个命令会输出当前节点实际加载的dataDir、clientPort、server.*列表。不同节点之间一对比,基本能立刻发现是哪台的配置没同步。

5.3 myid 目录权限问题:启动报错却不一定直接提示

很多公司的服务器会创建专用账号来跑大数据组件,比如hadoop用户。如果你用 root 下载并解压了 ZooKeeper,再用 hadoop 用户启动,dataDir 目录的属主可能是 root,导致节点无法写入 myid 对应的数据文件。

常见的表现形式是:启动脚本显示STARTED,但几秒后进程消失;或者启动时直接抛Unexpected exception causing shutdown。解决办法也很简单:

chown -R hadoop:hadoop /opt/zookeeper chown -R hadoop:hadoop /data/zookeeper

建议初始化阶段就统一好运行用户,不要在生产环境用 root 跑 ZooKeeper。进程隔离和权限控制是集群长期稳定运行的基本保障。

5.4 之前搭过单机版或伪分布式,残留数据引发集群异常

这是“复现路径最多”的坑:你可能会在同一台机器上先跑过单机版 ZooKeeper,dataDir 里已经积累了旧的事务日志和快照;后来配置了集群模式,却忘了把 dataDir 换个全新的目录,或者没有清空旧数据。

结果是节点启动时从旧日志里恢复出和历史状态不一致的快照,连入集群后可能出现各种诡异的数据错乱问题。

如果你确认旧数据无所谓,可以直接清空重建:

rm -rf /data/zookeeper/data/* mkdir -p /data/zookeeper/data echo 1 > /data/zookeeper/data/myid

更稳妥的方式是规划目录时就把测试环境和生产环境的数据目录分开,每个环境用独立路径,互不干扰。

5.5 会话频繁过期、客户端连接经常断

集群搭建完成后,如果业务方反馈“连接经常断”“Session expired”,先别急着怀疑代码。按这个思路排:

  • zkServer.sh status是否稳定有 Leader
  • 各节点系统负载和 GC 是否过高
  • JVM 堆内存是否给得过大或者过小
  • 网络是否存在间歇性丢包、延迟抖动

ZooKeeper 的设计目标是低延迟协调,对 GC 停顿和网络抖动比较敏感。如果节点频繁 Full GC,它会暂时不响应心跳,集群就会认为节点失联,从而触发重新选举或会话超时。这种情况下,调整 JVM 堆内存、减少单机上的客户端连接数,通常比改业务代码更有效。

5.6 通过zookeeper.out日志定位问题的建议

最后一招也是最重要的一招:养成看日志的习惯。zookeeper.out是整个 ZooKeeper 进程的 stdout/stderr 输出,日志里会打印工作目录、加载配置路径、启动身份、每台节点的连接状态。

排查故障时,我一般按“端到端”链路来做:客户端到 2181 通不通,节点到节点 2888/3888 通不通,配置文件是否一致,myid 是否一一对应,时间是否同步,日志中到底卡在哪一步。把这六项过一遍,90% 的搭建期问题都能定位出来。

错误信息往往藏在日志中而不是 status 里。你可能会看到一个节点 status 变成follower,但实际日志里一直输出连接不上某个地址,说明它的“心跳是好的,数据同步是坏的”。这种细微差别,只靠 status 是看不出来的。

6. 集群的日常维护与横向扩容建议

6.1 在线扩容还是停机扩容:多数场景直接选择停机扩容

ZooKeeper 3.5 之后支持动态重新配置(reconfig),可以实现在线加节点、下线节点。但动态 reconfig 需要额外开启配置和权限设置,操作复杂度比较高,很多存量集群也没有预先开启相关参数。对于大多数团队,我建议采用传统的停机扩容方式,步骤简单、可回退、符合现有运维习惯。

整体流程如下:

  1. 把新节点安装好 JDK、解压 ZooKeeper、创建 dataDir 和 myid
mkdir -p /data/zookeeper/data echo 4 > /data/zookeeper/data/myid # 假设新节点编号为4
  1. 在所有旧节点和新增节点的zoo.cfg中追加server.4=node04:2888:3888

  2. 逐台滚动重启所有节点。注意,不是同时重启所有节点,而是一台重启并确认它恢复 follower 角色后,再重启下一台

  3. 最后启动新节点,确认它也加入集群并且状态是 follower

滚动重启期间,集群始终能维持多数派可用,对上层业务的冲击最小。整个过程最怕的是“一次性把所有节点都重启了”,如果第一台刚起来、第二台还没起来时出问题,集群可能直接不可用。

6.2 Observer 模式:跨机房扩展读能力但不给选举增加负担

如果要把集群扩展到异地机房,或者某个机房只承担读流量,不建议直接把它加成一个普通 Follower,因为参与投票的节点越多,选举耗时越长,集群整体可用性反而下降。更好的做法是把它配置成 Observer。

Observer 的行为是:数据完全同步,但投票和选举都不参与。配置方式和普通 Follower 几乎一样,只是server.N行末尾加一个:observer标识:

server.4=node04:2888:3888:observer

另外在zoo.cfg中需要设置peerType=observer只对当前节点生效。这种方式非常适合做跨地域灾备和读写分离,很多大集群都是“多个 Follower + 若干 Observer”的组合。

6.3 数据目录的日常监控与清理策略

即使配了autopurge,也要在运维侧关注数据目录的增长情况。长期运行的 ZooKeeper,dataDir/dataLogDir 下的目录结构大约是这样:

/data/zookeeper/data/version-2/snapshot.xxxxx /data/zookeeper/data/version-2/log.xxxxx

其中snapshot.开头的是内存快照,log.开头的是事务日志。这些文件都是可清理的,前提是清理策略正确:要么靠autopurge自动清,要么停服后手动清。不能在生产运行时直接rm -f正在写的事务日志,否则可能破坏数据恢复流程。

我建议在监控面板上给 dataDir 和 dataLogDir 的磁盘使用率加上告警,阈值设在 70%。ZooKeeper 数据目录写满导致的故障,是最让人憋屈的故障类型——它不是突然发生的,而是被慢慢拖死的。

6.4 与 Hadoop HA、Kafka 集群的关系:ZooKeeper 定位是协调者

搭好 ZooKeeper 之后,下一步很可能是把它和 Hadoop、Kafka 等组件整合。在 Hadoop HA 场景中,NameNode 的 Active/Standby 切换依赖 ZooKeeper 上的临时节点和分布式锁机制,两个 NameNode 谁先在 ZooKeeper 上抢到锁,谁就是 Active。如果 ZooKeeper 集群本身不健康,HDFS 的自动故障转移就会失灵。

在 Kafka 2.x 时代,Kafka 集群的 Controller 选举和元数据管理同样依赖 ZooKeeper。虽然 Kafka 3.x 开始引入 KRaft 模式替代 ZooKeeper,但大量存量集群仍然在用基于 ZooKeeper 的架构,所以掌握 ZooKeeper 集群搭建依旧是大数据运维的基本功。

最后再分享一个我在多次搭建和扩容中总结出来的经验:ZooKeeper 集群的维护重点不在于配置多花哨,而在于一致性——配置保持一致、myid 与编号保持一致、时间保持一致、权限保持一致。任何一个“差不多”的环节,都会在故障切换的瞬间放大成不可用的后果。搭建步骤本身不复杂,真正拉开差距的,是故障处理和运维安排时你能不能把每一步都做到干净彻底。

返回列表