Skip to content

Zookeeper:单机与运维 ​

ZK 是 Kafka、Nacos、Dubbo 的老搭档。它本身很简单,出事基本集中在磁盘、会话超时、集群状态三点。

生产集群的搭建步骤见 Kafka 的 Zookeeper 模式。这一节补单机环境与日常运维。

一、安装 ​

bash
cd /opt
wget https://downloads.apache.org/zookeeper/zookeeper-3.9.2/apache-zookeeper-3.9.2-bin.tar.gz
tar xf apache-zookeeper-3.9.2-bin.tar.gz
ln -sfn /opt/apache-zookeeper-3.9.2-bin /opt/zookeeper

java -version
text
openjdk version "11.0.24" 2024-07-16 LTS

ZK 3.9 需要 Java 8+,推荐 11 或 17。

ini
# /opt/zookeeper/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper
clientPort=2181
maxClientCnxns=600

# 关键:不设会积累大量快照
autopurge.snapRetainCount=3
autopurge.purgeInterval=24

# 关键:不配白名单,四字命令全部禁用
4lw.commands.whitelist=stat,ruok,mntr,conf,cons,srvr,dirs

# 单机不写 server.N;集群才写
# server.1=10.0.0.21:2888:3888
bash
mkdir -p /data/zookeeper
useradd -r -s /sbin/nologin zookeeper
chown -R zookeeper:zookeeper /data/zookeeper /opt/zookeeper

4lw.commands.whitelist 从 3.5 起生效

不配这一项时,echo ruok | nc 会返回 ruok is not executed because it is not in the whitelist。这不是服务坏了,是安全默认值。

二、堆内存 ​

ZK 默认堆很小(512MB 左右),节点多时容易 Full GC。

bash
# /opt/zookeeper/bin/zookeeper-env.sh
export SERVER_JVMFLAGS="-Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=20"
bash
bin/zkServer.sh start
bin/zkServer.sh status
text
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone

Mode: standalone / leader / follower 三选一,看到 looking 就是没选出 leader。

三、四字命令 ​

bash
echo ruok | nc 127.0.0.1 2181
echo stat | nc 127.0.0.1 2181
echo mntr | nc 127.0.0.1 2181 | head -20
echo cons | nc 127.0.0.1 2181 | head
echo dirs | nc 127.0.0.1 2181
text
imok

Zookeeper version: 3.9.2-..., built on 2024-02-09
Clients:
 /10.0.0.21:51234[1](queued=0,recved=124,sent=124)

Latency min/avg/max: 0/0.31/12
Received: 1842
Sent: 1842
Connections: 1
Outstanding: 0
Zxid: 0x1f4
Mode: standalone
Node count: 128

mntr 是给监控用的键值对:

text
zk_version	3.9.2-...
zk_avg_latency	0
zk_max_latency	12
zk_min_latency	0
zk_packets_received	18424
zk_packets_sent	18422
zk_num_alive_connections	3
zk_outstanding_requests	0
zk_server_state	standalone
zk_znode_count	128
zk_watch_count	12
zk_ephemerals_count	8
zk_approximate_data_size	18432
zk_open_file_descriptor_count	86
zk_max_file_descriptor_count	65535
指标关注点
zk_avg_latency正常 < 10ms,突增说明磁盘慢
zk_outstanding_requests持续 > 0 = 请求堆积
zk_watch_count异常大(几十万)= 有客户端狂注册 watch,内存会涨
zk_ephemerals_count临时节点数,断了不清理会一直涨
zk_znode_count节点总数
zk_open_file_descriptor_count接近上限会连不上

四、客户端操作 ​

bash
/opt/zookeeper/bin/zkCli.sh -server 127.0.0.1:2181
text
[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[zookeeper, kafka, nacos]

[zk: ...] get /kafka/brokers/ids/1
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://10.0.0.21:9092"],...}

[zk: ...] stat /kafka
cZxid = 0x1f4
ctime = Tue Oct 27 19:10:02 CST 2026
mZxid = 0x1f4
mtime = Tue Oct 27 19:10:02 CST 2026
pZxid = 0x20a
cversion = 12
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 2

常用:

bash
ls /path
get /path
create /path value
set /path value
delete /path
rmr /path            # 递归删除(3.5+ 是 deleteall)
ls -R /path

别手改 Kafka/Nacos 在 ZK 里的节点

/kafka/brokers/ids、/nacos 下的数据是服务自己维护的。手改极容易让集群进入不一致状态,而且很难恢复。要改配置请改服务端配置文件后重启。

五、磁盘与快照 ​

bash
du -sh /data/zookeeper/*
ls -lh /data/zookeeper/version-2 | tail -5
text
128M	/data/zookeeper/version-2
4.0K	/data/zookeeper/myid

-rw-r--r-- 1 zookeeper zookeeper  64M Oct 27 23:20 snapshot.1f4a2b
-rw-r--r-- 1 zookeeper zookeeper 128M Oct 27 23:21 log.1f4a2c
  • snapshot.* 是数据快照。
  • log.* 是事务日志(WAL)。
  • autopurge 没开的话,这两类文件会一直涨。

手动清理只能在停机时做,且要保留最新的 3 个快照:

bash
systemctl stop zookeeper
cd /data/zookeeper/version-2
ls -t snapshot.* | tail -n +4 | xargs -r rm
ls -t log.* | tail -n +4 | xargs -r rm
systemctl start zookeeper

事务日志要单独放盘

ZK 每次写都要 fsync WAL。如果 WAL 和数据快照在同盘且盘很忙,写入延迟会飙。生产建议 dataLogDir 指到独立 SSD:

ini
dataDir=/data/zookeeper
dataLogDir=/data/zookeeper-log

六、会话与超时 ​

客户端连不上、频繁重连:

bash
grep -Ei 'session|expired|timeout' /opt/zookeeper/logs/zookeeper.log 2>/dev/null | tail
# 没配 log4j 时看 stdout
journalctl -u zookeeper -n 50 --no-pager

ZK 的会话超时由客户端提议、服务端裁决,最终取 min(客户端提议, 2 * tickTime, maxSessionTimeout)。

常见原因:

现象原因
客户端频繁 SESSION EXPIRED网络抖动 / GC 停顿超过会话超时
临时节点凭空消失会话过期,ephemeral 节点被删
大量 zk_watch_count客户端每个请求都注册 watch,没清理
Too many connectionsmaxClientCnxns 限制(单 IP)

七、常见故障 ​

bash
bin/zkServer.sh status
text
Mode: looking

三台都 looking:互相连不上(2888/3888)、myid 错、或者只有 1 台活着(选不出多数)。

bash
ss -lntp | grep -E '2181|2888|3888'
echo srvr | nc 127.0.0.1 2181

Not serving requests 说明它还在恢复/选举。

磁盘满的表现:

text
java.io.IOException: No space left on device

ZK 会直接失去写能力,进而导致依赖它的 Kafka/Nacos 全挂。ZK 所在分区必须单独监控。

八、踩过的坑 ​

现象根因处置
四字命令返回 not in the whitelist3.5+ 默认禁用配 4lw.commands.whitelist
Mode: looking 一直不结束端口不通 / myid 错 / 多数派不足查 2888/3888 与 myid
磁盘被 version-2 占满没开 autopurge开自动清理 + 手动清旧文件
延迟突然升高WAL 与数据同盘、磁盘忙dataLogDir 独立 SSD
客户端频繁 session expired客户端 GC 停顿调大 sessionTimeout,优化客户端
maxClientCnxns 超限单 IP 连接过多调大,或用连接复用
集群只剩 1 台另外两台挂了单台无法选主,必须恢复多数派
启动报 Unable to load database快照损坏用最新完整快照恢复,或从其他节点同步