告别ZooKeeper:深入解析Kafka KRaft模式的环境搭建与演进意义

2026/02/06 Kafka 共 4042 字,约 12 分钟

告别ZooKeeper:深入解析Kafka KRaft模式的环境搭建与演进意义

Apache Kafka作为流处理领域的基石,其高吞吐、可扩展、持久化的特性使其成为现代数据架构的核心组件。然而,在相当长的时间里,Kafka的一个“甜蜜的负担”是其对Apache ZooKeeper的强依赖。ZooKeeper负责管理Kafka的元数据(如Broker、Topic、Partition信息)和控制器选举,但这套架构也带来了运维复杂度高、故障域耦合等问题。自Kafka 2.8版本(2021年)开始引入的KRaft(Kafka Raft)模式,标志着Kafka迈向“去ZooKeeper化”的关键一步。本文将带你从环境搭建入手,深入理解KRaft的运作机制与演进价值。

一、 为何要“去ZooKeeper”?KRaft的诞生背景

在传统架构中,Kafka集群需要同时维护两套系统:

  1. Kafka Broker集群:处理数据的存储与读写。
  2. ZooKeeper集群:通常为3或5个节点,存储集群元数据并选举Controller。

这种架构存在几个痛点:

  • 运维复杂度翻倍:需要部署、监控、维护两套分布式系统,对运维人员要求高。
  • 性能瓶颈:元数据操作需要与ZooKeeper交互,在大规模集群(如数十万个分区)下,ZooKeeper可能成为性能瓶颈和单点故障源(尽管ZK本身是分布式的,但相对于Broker是独立的故障域)。
  • 资源浪费:需要为ZooKeeper单独准备机器资源。
  • 控制器故障恢复慢:Controller故障后,需要通过与ZooKeeper交互进行新的选举,恢复时间较长。

KRaft模式的核心思想是:让Kafka使用自身实现的Raft共识协议来管理元数据,从而消除对ZooKeeper的外部依赖。在KRaft模式下,一部分Kafka Broker被指定为“控制器节点”,它们组成一个Raft仲裁组,直接持久化元数据变更日志并达成共识。这使Kafka成为一个真正自包含的系统。

二、 KRaft模式核心概念与角色

在搭建之前,需要理解KRaft中的几个关键角色:

  • Controller节点:运行KRaft协议的Broker。一个集群中,有多个Controller节点组成一个仲裁组
  • 仲裁组:所有Controller节点的集合,通过Raft协议选举出一个Active Controller,其他为Follower。Active Controller负责处理所有元数据变更请求。
  • Broker节点:既可以作为普通的Broker处理数据请求,也可以同时担任Controller角色(进程级混合模式),或者物理分离(进程级专用模式)。
  • 元数据日志:一个特殊的内部Topic(__cluster_metadata),由仲裁组共同维护,记录了所有元数据的变更历史,是Raft协议中的“日志”。

三、 实战:搭建一个三节点的KRaft模式Kafka集群

我们将搭建一个包含3个节点的集群,每个节点同时扮演Broker和Controller角色(混合模式),这是最常见和简单的部署方式。

步骤1:环境准备与软件下载

假设你有三台服务器(或本地三个端口),IP/主机名分别为 node1, node2, node3。确保它们之间网络互通,并已安装Java 11或更高版本。

Apache Kafka官网下载最新版本(建议3.0+,本文以3.5.0为例)。

# 在所有节点执行
wget https://downloads.apache.org/kafka/3.5.0/kafka_2.13-3.5.0.tgz
tar -xzf kafka_2.13-3.5.0.tgz
cd kafka_2.13-3.5.0

步骤2:配置KRaft集群

Kafka的配置文件位于 config/kraft/ 目录下。我们需要为每个节点创建一份配置文件。首先,生成一个唯一的集群ID(在所有节点中必须一致)。

# 在任一节点执行,生成集群ID,并记录下来(如:M-kHyTToS6qcih5VbVq1MQ)
./bin/kafka-storage.sh random-uuid

接下来,为每个节点准备配置文件。以 node1 为例,创建 config/kraft/server-node1.properties

# node1.properties
# 节点的唯一ID,三个节点分别设为1,2,3
node.id=1
# 步骤1生成的集群ID
process.roles=broker,controller
inter.broker.listener.name=PLAINTEXT
controller.listener.names=CONTROLLER
listeners=PLAINTEXT://:9092,CONTROLLER://:9093
advertised.listeners=PLAINTEXT://node1:9092
# 控制器仲裁组,格式为 `id@host:port`,列出所有controller节点
controller.quorum.voters=1@node1:9093,2@node2:9093,3@node3:9093
# 日志目录
log.dirs=/tmp/kraft-combined-logs-node1
num.partitions=1
default.replication.factor=3
min.insync.replicas=2

node2node3 创建类似配置,主要修改 node.idadvertised.listeners 以及对应的主机名和端口(确保不冲突)。

步骤3:格式化存储目录并启动

重要:在首次启动前,必须用集群ID格式化每个节点的存储目录。

# 在 node1 上执行
./bin/kafka-storage.sh format -t <你生成的集群ID> -c ./config/kraft/server-node1.properties
# 在 node2, node3 上执行对应命令,指定各自的配置文件

格式化完成后,启动每个节点:

# 在每个节点上,使用各自的配置文件启动
./bin/kafka-server-start.sh -daemon ./config/kraft/server-node1.properties

步骤4:验证集群

在所有节点启动后,可以使用Kafka脚本验证集群状态。

# 在任一节点执行,查看集群元数据日志信息
./bin/kafka-metadata-shell.sh --cluster-id <你的集群ID> --snapshot /tmp/kraft-combined-logs-node1/__cluster_metadata-0/00000000000000000000.log
# 在shell中执行 `ls /` 查看根元数据

# 创建一个Topic来测试
./bin/kafka-topics.sh --bootstrap-server node1:9092 --create --topic test-kraft --partitions 3 --replication-factor 3
# 列出Topic
./bin/kafka-topics.sh --bootstrap-server node1:9092 --list
# 描述Topic详情
./bin/kafka-topics.sh --bootstrap-server node1:9092 --describe --topic test-kraft

如果以上命令都能成功执行,恭喜你,一个不依赖ZooKeeper的Kafka KRaft集群已经搭建完成!

四、 KRaft vs ZooKeeper:架构演进的优势分析

通过搭建过程,我们可以直观感受到KRaft的简洁性。从架构角度看,其优势显著:

  1. 简化部署与运维:只需维护一套Kafka集群,无需额外的ZooKeeper集群。配置、监控、备份都得到统一。
  2. 提升可扩展性与性能:元数据操作直接在Kafka内部处理,利用Raft日志的线性追加特性,能够更好地支持超大规模分区(官方称可支持百万级分区)。元数据传播路径更短,延迟更低。
  3. 更强的故障恢复与一致性:Raft协议提供了强一致性的保证。Controller故障切换在KRaft仲裁组内部完成,速度更快(秒级甚至亚秒级),且选举过程对数据客户端更透明。
  4. 更清晰的元数据模型:元数据以日志形式存储,便于理解、调试和进行时间点恢复(Snapshot)。
  5. 为未来功能铺路:去除了ZooKeeper这一外部依赖,使得Kafka团队可以更自由地设计和实现新功能,如更灵活的分区再平衡、更细粒度的安全模型等。

五、 迁移考量与生产建议

虽然KRaft是未来,但迁移需要谨慎规划:

  • 版本选择:生产环境建议使用Kafka 3.3+版本,其KRaft实现已宣布生产就绪(从3.3版本开始,KRaft元数据模式在功能上完成了对ZooKeeper模式的100%覆盖)。
  • 迁移路径:Kafka提供了从ZooKeeper模式到KRaft模式的滚动迁移工具,允许在不停服的情况下逐步迁移。但这是一项复杂的操作,需在测试环境充分演练。
  • 监控重点:在KRaft模式下,需要重点关注 ActiveControllerCountLastAppliedOffsetQuorumSize 等KRaft特有的监控指标。
  • 配置优化:根据集群规模调整 metadata.log.max.record.bytes.between.snapshots(控制快照频率)等参数。

结语

从依赖ZooKeeper到拥抱KRaft,是Apache Kafka走向成熟与自治的重要里程碑。这不仅简化了系统架构,降低了运维负担,更在性能、可扩展性和可靠性上为下一代数据流平台奠定了坚实基础。对于新部署的集群,强烈建议直接采用KRaft模式。对于已有集群,则应开始制定迁移计划,逐步拥抱这个更简洁、更强大的Kafka新时代。通过本文的搭建实践与原理剖析,希望你能更好地理解并驾驭这一变革。

文档信息

Search

    Table of Contents