Skip to content

KRaft 与元数据控制器

This content is not available in your language yet.

KRaft 把控制器选举、元数据存储和传播变成 Kafka 自己维护的 Raft quorum;控制器只应用已经提交的 metadata record。

先给答案:KRaft 先复制元数据事实,再由控制器应用已提交记录

Section titled “先给答案:KRaft 先复制元数据事实,再由控制器应用已提交记录”

KafkaRaftClient 负责 term/epoch、投票、日志复制、high watermark 和 snapshot;QuorumController 消费 committed metadata records,确定性地更新 Topic、Partition、配置和节点状态。控制器不能把 leader 本地尚未提交的记录当作集群事实。

这样选主、恢复和元数据传播共享同一个提交边界,但也要求 offset 与 epoch 一起校验,snapshot 安装必须原子衔接后续日志。网络分区时宁可暂停无 quorum 的修改,也不能让两个控制器基于不同历史同时对外生效。

Voters -> KafkaRaftClient -> election / fetch / high watermark
|
v
committed metadata records
|
v
QuorumController state

KafkaRaftClient(raft/src/main/java/org/apache/kafka/raft/KafkaRaftClient.java:170)处理投票、epoch、fetch 和 snapshot。initialize(:486)建立状态,transitionToCandidate(:724)发起选举,quorum.transitionToLeader(:662)建立 leader state,handleFetchRequest(:1483)服务 follower 复制,appendAsFollower(:1831)和 appendAsLeader(:1863)处理两种追加。

QuorumController 位于 metadata/src/main/java/org/apache/kafka/controller/QuorumController.java:177。它作为 Raft listener 消费 committed records,更新 topic、partition、配置和节点状态,而不是直接接受未提交的任意修改。

latestSnapshot(KafkaRaftClient.java:452)发现快照,handleFetchSnapshotRequest(:1922)负责传输。恢复先安装一致快照,再继续应用快照 offset 之后的 committed records。

为什么控制器也做成日志状态机

Section titled “为什么控制器也做成日志状态机”

替代方案:单控制器直接写本地文件,再通过 RPC 推送。 为什么不行:控制器故障时还需要另一个选主和一致性协议;推送成功也不能保证新控制器从相同状态继续。 证据:KafkaRaftClient 负责 epoch、vote、fetch 和 high watermark,QuorumController 只消费提交记录,snapshot 则控制重放成本。

场景 现象 原因 规避
只比较 offset follower 追加错误分支 epoch 也可能不同 同时比较 epoch 和 offset
leader append 就认为 committed 数据已看到但不可见 尚未达到 quorum HW 用 high watermark 判断提交
snapshot 中途读取状态 元数据暂时不一致 快照切换边界错误 以 snapshot offset 原子切换

“可复制日志 + 确定性状态机”可以统一选主、恢复、审计和版本传播;状态机不能依赖未提交事件。

面试锚点

  • KRaft 解决了 ZooKeeper 时代哪些耦合?
  • Raft high watermark 为什么重要?
  • metadata snapshot 如何缩短恢复?