Kafka 2.8起引入KRaft模式,Java应用无需修改代码即可脱离ZooKeeper依赖,因服务端用内置Raft替代ZooKeeper协调,客户端仍使用标准API与Broker交互,仅需确保集群已正确配置KRaft模式。

Kafka 从 2.8 版本开始引入 KRaft(Kafka Raft)模式,Java 应用本身并不直接参与 Raft 协议的运行,而是通过 Kafka 客户端(如 AdminClient、KafkaProducer、KafkaConsumer)与已启用 KRaft 模式的 Kafka 集群交互。真正“摆脱 ZooKeeper 依赖”的核心,在于 Kafka 服务端自身用内置 Raft 共识机制替代了外部协调组件——Java 代码无需改动,只需连接正确的集群地址即可。
Java 应用无需修改 Raft 相关逻辑
KRaft 是服务端能力,不是客户端协议。Java 程序仍使用标准 Kafka API:
- 创建 Topic、调整分区、查询元数据等操作,调用
AdminClient接口,底层请求由 Broker 转发给当前 Controller(Raft Leader),Controller 直接写入内置元数据日志(__cluster_metadata主题),不再访问 ZooKeeper。 - Producer 和 Consumer 连接
bootstrap.servers列表中的任意 Broker 地址,Broker 内部自动识别 Controller 角色并路由请求,整个过程对 Java 代码完全透明。 - 旧版依赖 ZooKeeper 的配置项(如
zookeeper.connect)在 KRaft 模式下已被废弃,Java 客户端配置中不应再出现。
关键前提是服务端已启用 KRaft 模式
Java 应用能“无感”脱离 ZooKeeper,前提是 Kafka 集群本身已正确部署为 KRaft 模式。这需要:
- 使用 Kafka 3.5.1 或更高版本(早期 KRaft 存在元数据损坏风险,如 CVE-2025-27817);
- Broker 配置中明确指定
process.roles=broker,controller(或分离部署时设为controller/broker); - 设置
node.id、controller.quorum.voters(列出所有 controller 节点的 ID 和地址); - 禁用
zookeeper.connect,并确保未启动 ZooKeeper 进程。
元数据操作行为变化(Java 开发者可感知)
虽然代码不变,但实际表现有明显优化:
立即学习“Java免费学习笔记(深入)”;
- Topic 创建、删除、分区重分配等操作响应更快,因元数据变更直写 Raft 日志,无需跨系统同步;
- Controller 故障转移时间从秒级降至毫秒级,消费者组再平衡、Leader 选举更稳定,Java 消费端抖动减少;
- 不再出现类似
zk disconnected、controller not available等源于 ZooKeeper 连接问题的日志,异常排查路径更短。
迁移时 Java 侧需注意的兼容点
绝大多数 Java 应用无需调整,但以下场景建议检查:
- 若代码中硬编码了 ZooKeeper 客户端(如
CuratorFramework)用于读取 offset 或 topic 列表,这部分逻辑必须移除或改用AdminClient.listTopics()、listConsumerGroupOffsets()等原生接口; - Spring Kafka 2.9+ 已适配 KRaft,旧版本(如 2.7.x)可能在自动创建 topic 时触发不兼容警告,建议升级;
- 监控告警中依赖 ZooKeeper 健康状态(如 ZK session 数、watcher 数)的指标应停用,转而关注 Kafka 自身指标:如
kafka.controller:type=KafkaController,name=ActiveControllerCount、UnderReplicatedPartitions等。



















