5月31日 16:34

Kafka 为什么曾经依赖 ZooKeeper?它到底负责什么?

在早期和大量存量 Kafka 集群里,ZooKeeper 负责保存和协调集群元数据:Broker 注册、Controller 选举、Topic 与分区信息、部分配置和权限数据。它不是 Kafka 的消息存储层,真正的消息仍然写在 Broker 本地日志里。ZooKeeper 更像一个一致性协调中心,帮助 Kafka 判断“谁还活着、谁来当 Controller、元数据现在是什么状态”。

ZooKeeper 管哪些事

Broker 启动后会连接 ZooKeeper,并在 /brokers/ids 下创建临时节点。临时节点和会话绑定,如果 Broker 宕机或网络断开超过会话超时时间,节点会消失,其他组件就能感知 Broker 不可用。这个机制让 Kafka 能快速发现集群成员变化。

Controller 选举也依赖 ZooKeeper。多个 Broker 会竞争创建 /controller 节点,创建成功者成为 Controller。Controller 负责分区 leader 选举、副本状态变化、Topic 创建删除等集群级动作。ZooKeeper 在这里提供的是互斥和通知能力,避免多个 Broker 同时认为自己是控制者。

text
/brokers/ids/1 # Broker 注册信息 /controller # 当前 Controller /brokers/topics/orders # Topic 分区与副本元数据 /config/topics/orders # Topic 级配置 /kafka-acl/Topic/orders # ACL 信息

这些路径有助于理解 ZooKeeper 的定位:它保存的是元数据和状态,不负责传输业务消息。

Consumer offset 也在 ZooKeeper 吗

这要看 Kafka 版本和客户端。早期 Consumer 会把 offset 写到 ZooKeeper 的 /consumers 路径下,但新版本 Kafka 默认把 offset 存到内部 topic __consumer_offsets。所以面试或排查时不能简单说“ZooKeeper 管 Consumer offset”,更准确的说法是:旧消费者协议依赖 ZooKeeper,新消费者组协调和 offset 存储主要由 Kafka 自己完成。

这个细节很容易踩坑。运维老集群时,如果还有旧客户端,ZooKeeper 里可能仍能看到 consumer 路径;新集群则更多关注 Group Coordinator 和内部 topic。判断时看客户端版本和 kafka-consumer-groups.sh 查询结果,比背路径更可靠。

ZooKeeper 配置要注意什么

Kafka 侧至少要配置连接串和超时。生产环境不要只放一个 ZooKeeper 节点,通常使用 3 或 5 个节点组成 quorum。节点数用奇数,是为了在故障时仍能形成多数派。

properties
# server.properties zookeeper.connect=zk1:2181,zk2:2181,zk3:2181/kafka-prod zookeeper.connection.timeout.ms=6000 zookeeper.session.timeout.ms=18000
properties
# zoo.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/var/lib/zookeeper clientPort=2181 server.1=zk1:2888:3888 server.2=zk2:2888:3888 server.3=zk3:2888:3888

zookeeper.session.timeout.ms 不是越短越好。太短会把短暂网络抖动误判成 Broker 下线,引发 Controller 处理分区变化;太长又会让真实故障发现变慢。生产里要结合网络质量、GC 暂停和业务可用性要求调整。

KRaft 出现后 ZooKeeper 还重要吗

Kafka 新版本已经引入 KRaft,用 Kafka 自己的 Raft 元数据 quorum 替代 ZooKeeper。新建集群可以优先评估 KRaft,部署和运维链路更简单。但很多公司仍有 ZooKeeper 模式的存量集群,迁移涉及版本、工具链、监控、备份和回滚方案,不是改一行配置就结束。

因此 ZooKeeper 仍然是高价值知识点。理解它能帮助你排查 Controller 抖动、Broker 频繁上下线、Topic 元数据异常和老集群权限问题。

追问

ZooKeeper 会保存 Kafka 的消息数据吗?

不会,Kafka 消息写在 Broker 的日志目录里,ZooKeeper 保存的是元数据和协调状态。把 ZooKeeper 当消息存储是常见误解,也会导致错误的备份方案。备份 ZooKeeper 只能保护部分元数据,不能恢复业务消息。真正的数据可靠性要看 topic 副本数、ISR、acks 和 Broker 磁盘。

ZooKeeper 挂了 Kafka 会立刻不可用吗?

如果 ZooKeeper 集群只是少数节点故障,多数派还在,Kafka 通常可以继续工作。如果 ZooKeeper quorum 整体不可用,已有 leader 分区可能还能短时间处理读写,但创建 Topic、Controller 选举、Broker 变更等元数据操作会受影响。边界在于“已有数据面”和“控制面变更”不是一回事。生产上不能因为消息还能写就忽视 ZooKeeper 故障。

为什么 ZooKeeper 要部署奇数个节点?

ZooKeeper 依赖多数派确认,3 个节点允许坏 1 个,5 个节点允许坏 2 个。偶数节点不会提升多数派容错能力,反而增加成本和通信开销。比如 4 个节点仍然需要 3 个形成多数,容错能力和 3 节点一样。常见取舍是中小集群用 3 个,跨机房或更高可用要求再评估 5 个。

Kafka 迁到 KRaft 后就不用理解 ZooKeeper 了吗?

新建 KRaft 集群确实不再依赖 ZooKeeper,但存量系统、面试和故障复盘里仍经常遇到 ZooKeeper 模式。迁移还要考虑 Kafka 版本、元数据迁移、监控指标变化和回滚路径。只知道 KRaft 的配置,不理解旧模式,很难解释老集群 Controller 抖动或 Broker 注册异常。更稳的做法是同时理解两套元数据管理方式。

ZooKeeper 相关故障通常怎么排查?

先看 Kafka Broker 日志里是否有 session expired、controller moved、zookeeper disconnected 等关键字。再检查 ZooKeeper 四字命令或监控指标,例如连接数、延迟、leader/follower 状态和磁盘 fsync 时间。很多问题不是 ZooKeeper 进程挂了,而是网络抖动、磁盘慢或 Broker 长 GC 导致会话过期。排查时要把 Kafka 日志、ZooKeeper 日志和节点资源放在同一时间线看。

标签:Kafka