外观
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 -versiontext
openjdk version "11.0.24" 2024-07-16 LTSZK 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:3888bash
mkdir -p /data/zookeeper
useradd -r -s /sbin/nologin zookeeper
chown -R zookeeper:zookeeper /data/zookeeper /opt/zookeeper4lw.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 statustext
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standaloneMode: 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 2181text
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: 128mntr 是给监控用的键值对:
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:2181text
[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 -5text
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.1f4a2csnapshot.*是数据快照。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-pagerZK 的会话超时由客户端提议、服务端裁决,最终取 min(客户端提议, 2 * tickTime, maxSessionTimeout)。
常见原因:
| 现象 | 原因 |
|---|---|
客户端频繁 SESSION EXPIRED | 网络抖动 / GC 停顿超过会话超时 |
| 临时节点凭空消失 | 会话过期,ephemeral 节点被删 |
大量 zk_watch_count | 客户端每个请求都注册 watch,没清理 |
Too many connections | maxClientCnxns 限制(单 IP) |
七、常见故障
bash
bin/zkServer.sh statustext
Mode: looking三台都 looking:互相连不上(2888/3888)、myid 错、或者只有 1 台活着(选不出多数)。
bash
ss -lntp | grep -E '2181|2888|3888'
echo srvr | nc 127.0.0.1 2181Not serving requests 说明它还在恢复/选举。
磁盘满的表现:
text
java.io.IOException: No space left on deviceZK 会直接失去写能力,进而导致依赖它的 Kafka/Nacos 全挂。ZK 所在分区必须单独监控。
八、踩过的坑
| 现象 | 根因 | 处置 |
|---|---|---|
四字命令返回 not in the whitelist | 3.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 | 快照损坏 | 用最新完整快照恢复,或从其他节点同步 |