kraft的设计与实现
一、背景
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 的默认架构,为数据基础设施的现代化提供强力支撑。