一、背景
1.1 为什么 Zookeeper 成为了 Kafka 的瓶颈
Zookeeper 曾是 Kafka 集群中元数据存储与协调的核心组件,但在大规模生产环境下逐渐暴露出以下瓶颈:
-
扩展性受限:Zookeeper 的 znode 数据结构对节点数量和大小都有上限,不适合承载成千上万个 topic 和 partition 的元数据。
-
高访问压力:Kafka 的 controller 需要频繁读写 Zookeeper(如 ISR 状态、分区 leader 选举等),Zookeeper 的同步机制易引发延迟。
-
watch 机制脆弱:Zookeeper 的一次性触发监听机制容易漏掉事件,并在大规模变动时引发惊群效应。
-
运维复杂:Kafka 的稳定性高度依赖于 Zookeeper 的可用性,增加了部署、监控和故障排查的复杂度。
-
架构不匹配:Kafka 是高吞吐的日志系统,而 Zookeeper 更适合协调少量强一致的数据,两者设计理念不一致。
1.2 KRaft 是什么
KRaft(Kafka Raft Metadata Mode)是 Kafka 原生实现的一套基于 Raft 协议的分布式一致性元数据管理系统。
KRaft 替代 Zookeeper 后,Kafka 将所有元数据写入内部主题 __cluster_metadata
中,控制器节点组成 Raft 仲裁集群进行主控选举、日志复制、事务提交等操作。
主要特性包括:
-
无需外部协调系统
-
基于 Raft 的强一致性元数据日志
-
支持快照、元数据事务(KIP-868)
-
Broker 与 Controller 解耦
1.3 KRaft 的诞生
KRaft 起始于 KIP-500,该提案提出彻底移除 ZooKeeper,Kafka 完全自主管理元数据。
随后多个 KIP 相继推动 KRaft 落地:
-
KIP-500:提出替换 ZooKeeper 的整体方案。
-
KIP-595:定义元数据存储格式与序列化机制。
-
KIP-631:详细设计 Raft-based Controller 架构。
-
KIP-630:设计新的 broker 注册与心跳协议。
-
KIP-868:支持元数据事务机制。
Kafka 从 2.8 开始支持 KRaft 模式(预览),至 3.3.1 被认为可用于生产环境。
二、KRaft 的实现
2.1 核心概念
-
KafkaRaftServer:KRaft 模式下 Kafka 实例的主类,可作为 broker、controller 或两者并存。
-
__cluster_metadata:Kafka 内部用于存储所有元数据的单分区日志主题,由 active controller 控制写入。
-
Controller Quorum:多个 controller 节点通过 Raft 构成的元数据仲裁组。
-
Active Controller:当前担任主控角色的 controller,负责所有元数据更改和复制,其他为热备份。
-
Broker Registration:Broker 启动时向 controller 注册,controller 分配 epoch 标识其生命周期。
-
Snapshot:元数据的定期快照,加快恢复速度。
-
Metadata Transactions:多个元数据操作作为事务一并提交,提高一致性与原子性(KIP-868)。
2.2 Controller 选举过程
KRaft 基于 Raft 协议完成控制器选主与日志复制:
-
Controller 启动,向仲裁组发起选举请求(RequestVote)。
-
其他节点根据日志新旧情况投票。
-
获得超半数投票后成为 Active Controller。
-
追加元数据记录到日志,其他 controller定时向Active Controller拉取元数据。
-
若 Active Controller 故障,重新触发选举。
所有变更需写入日志并被多数 controller 确认,才视为提交成功。
2.3 Controller 与 Broker 的数据同步
-
注册与心跳 :Broker 启动后通过
BrokerRegistrationRequest
注册,周期性发送心跳。 -
元数据获取:Broker 主动从 controller 拉取元数据更新。
-
受控下线 :Broker 请求关闭时,controller 转移其 leader,待迁移完成后返回
ShouldShutDown=true
。
KRaft 实现了控制面与数据面解耦,提升了弹性与可维护性。
2.4 快照与恢复机制
-
Active controller 会定期生成快照,保存所有元数据的最简描述。
-
快照为本地文件,用于减少日志回放量。
-
新 controller 加入时,先加载快照,再 replay 日志达到一致状态。
快照机制极大提升了 controller 故障恢复与选主切换的效率。
2.5 元数据事务实现
KIP-868 引入元数据事务,支持批量元数据修改的原子性提交:
-
事务结构包含
BEGIN
, 多条RECORD
, 和END
标识。 -
仅当
END
被多数 controller 同步确认后,事务才视为成功。 -
支持如"同时创建多个 topic 与配置修改"的一致性操作。
事务机制增强了 Kafka 元数据的可靠性与扩展性。
三、KRaft 的部署与运维建议
3.1 Controller 节点部署建议
-
建议使用奇数个 controller(3 或 5 个),减少维持集群可用的最小broker比例。
-
使用独立进程部署 controller,提高资源隔离与稳定性。
-
节点网络应低延迟、互通性良好。
3.2 Broker 与 Controller 共置部署注意事项
-
设置
process.roles=broker,controller
进行共置。 -
共置适用于测试环境或资源受限部署。
-
建议将 controller 的端口对外隔离,防止客户端误访问或者攻击。
3.3 快照与日志管理
-
配置快照生成频率与保留策略。
-
定期监控 controller 节点的快照与元数据日志空间。
3.4 升级与迁移路径
-
Kafka 2.8 引入 KRaft(实验),3.3.1 起生产可用。
-
KRaft 模式与 ZooKeeper 模式 不兼容,不可混用。
-
建议新集群优先使用 KRaft,旧集群等待后续版本支持在线迁移。
结语
KRaft 的引入标志着 Kafka 架构从"依赖外部协调系统"迈向"内生强一致性"的演进。它解决了 Zookeeper 带来的性能、复杂性与可靠性问题,为 Kafka 带来了更高的可扩展性、更好的集群一致性和更低的运维成本。未来,KRaft 将成为 Kafka 的默认架构,为数据基础设施的现代化提供强力支撑。