3. Kafka 集群部署:从单机到集群,再到 KRaft 模式

部署 Kafka,说白了就是搭一个能扛住生产压力的消息管道。我见过不少团队,开发环境跑单机挺顺,一上生产就各种脑裂、磁盘写爆、Controller 挂了集群瘫痪。嗯,这里面的坑,多半是部署阶段埋下的。

这一章,咱们从最基础的单机部署开始,一步步走到真正的集群搭建。然后我会聊聊 ZooKeeper 在旧版 Kafka 里到底扮演什么角色,最后重点介绍 KRaft 模式——这个去掉 ZooKeeper 的新玩法,我个人觉得是未来趋势。

3.1 单机部署:先跑起来再说

单机部署其实就三步:下载、解压、启动。但别小看它,很多配置项的理解,都是从单机开始的。

我的习惯: 学习任何中间件,我都会先在单机上跑一遍完整流程。这样出了问题,排查范围最小,能快速理解每个配置的作用。

具体步骤很简单:

  1. 从 Apache 官网下载 Kafka 二进制包(比如 kafka_2.13-3.5.0.tgz)
  2. 解压到指定目录,比如 /opt/kafka
  3. 修改 config/server.properties 里的 log.dirs,指向你的数据盘
  4. 启动 ZooKeeper(旧版需要):bin/zookeeper-server-start.sh config/zookeeper.properties
  5. 启动 Kafka:bin/kafka-server-start.sh config/server.properties

启动成功后,你可以用 kafka-topics.sh 创建一个测试主题,再用 kafka-console-producer.sh 和 kafka-console-consumer.sh 验证一下。能发能收,单机就通了。

注意: 单机部署时,broker.id 默认是 0。如果你以后要扩集群,记得提前规划好 ID 分配,别到时候冲突了。

3.2 集群搭建:三个节点起步

生产环境至少三个节点,这是铁律。为什么?因为 Kafka 的副本机制需要多数派才能正常工作。两个节点,挂一个就完蛋;三个节点,挂一个还能撑住。

搭建集群的核心步骤:

  • 准备三台机器(或三个容器),每台都装好 Kafka
  • 每台机器的 server.properties 里,broker.id 分别设为 0、1、2
  • zookeeper.connect 指向同一个 ZooKeeper 集群地址,比如 zk1:2181,zk2:2181,zk3:2181
  • 启动顺序:先启动所有 ZooKeeper 节点,再依次启动 Kafka Broker

集群启动后,你可以用 kafka-broker-api-versions.sh --bootstrap-server broker1:9092,broker2:9092,broker3:9092 来验证所有节点是否都在线。

关键参数:

  • broker.id:集群内唯一,不能重复
  • log.dirs:建议用多块磁盘,用逗号分隔,Kafka 会自动做数据均衡
  • num.partitions:默认分区数,生产环境建议设为 3 或更高
  • default.replication.factor:默认副本数,生产环境至少 2,推荐 3

我曾经遇到过一个案例:某团队把 default.replication.factor 设成了 1,结果一台机器磁盘坏了,整个主题的数据全丢。嗯,血的教训。

3.3 ZooKeeper 角色:集群的“大脑”

在 KRaft 模式出现之前,ZooKeeper 是 Kafka 集群的“大脑”。它负责三件事:

职责 说明
Controller 选举 从所有 Broker 中选出一个 Controller,负责分区 leader 的分配
元数据存储 记录主题、分区、副本、Broker 列表等集群元数据
集群成员管理 Broker 上下线时,ZooKeeper 能感知并通知 Controller

说白了,ZooKeeper 就是 Kafka 的“注册中心”加“协调器”。没有它,Broker 之间不知道谁活着谁死了,分区 leader 也没人管了。

但 ZooKeeper 本身也是个分布式系统,它也有自己的集群部署要求。这就带来了一个问题:你为了管好 Kafka,还得先搭一套 ZooKeeper 集群。运维成本翻倍了。

我的经验: ZooKeeper 集群最好用奇数节点(3、5、7),因为它的选举机制需要多数派。3 个节点能容忍 1 个挂掉,5 个能容忍 2 个。别省这点机器,否则 Kafka 集群的稳定性就是空中楼阁。

3.4 KRaft 模式:去掉 ZooKeeper 的新时代

Kafka 2.8 开始引入了 KRaft 模式,到了 3.x 版本已经逐步成熟。它的核心思想是:Kafka 自己管自己的元数据,不再依赖 ZooKeeper。

怎么做到的?KRaft 模式引入了一个新的角色叫 Controller(注意,这和旧版的 Controller 不是一回事)。新 Controller 是一个独立的进程,或者内嵌在 Broker 里,它使用 Raft 共识算法来管理元数据变更。

对比一下两种模式:

对比项 ZooKeeper 模式 KRaft 模式
依赖组件 Kafka + ZooKeeper 只有 Kafka
元数据存储 ZooKeeper 存储 Kafka 内部主题 __cluster_metadata
Controller 选举 依赖 ZooKeeper 临时节点 Raft 算法自选举
运维复杂度 高(需要维护两套集群) 低(一套集群搞定)
成熟度 非常成熟 持续完善中(3.x 已可用于生产)

KRaft 模式的部署也简单一些。你只需要在 server.properties 里配置 process.roles=broker,controller,然后指定 controller.quorum.voters 列表即可。

# KRaft 模式配置示例
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
注意: KRaft 模式下,node.id 替代了原来的 broker.id。而且 controller.quorum.voters 里的端口(9093)是 Controller 之间的通信端口,和客户端用的 9092 不一样。

我个人建议,新项目可以直接上 KRaft 模式。虽然它还在完善中,但 3.x 版本已经足够稳定。而且少维护一套 ZooKeeper,运维同学会感谢你的。

3.5 一张图看懂 Kafka 部署模式

下面这张图展示了从单机到集群,再到 KRaft 模式的演进路径。你可以看到 ZooKeeper 在旧模式中的位置,以及 KRaft 如何简化架构。

Kafka 部署模式演进图 Kafka 部署模式演进 单机模式 Broker (broker.id=0) ZooKeeper (单节点) 适合开发/测试环境 集群模式 (ZooKeeper) Broker 0 Broker 1 Broker 2 依赖 ZooKeeper 集群 KRaft 模式 Broker + Controller Broker + Controller Broker + Controller 无需 ZooKeeper 核心差异对比 单机模式:1 个 Broker + 1 个 ZooKeeper,适合学习测试 集群模式:3+ 个 Broker + 3+ 个 ZooKeeper,生产主流 KRaft 模式:3+ 个节点,每个节点同时扮演 Broker 和 Controller ZooKeeper 模式需要维护两套集群,运维成本高。 KRaft 模式去掉了 ZooKeeper,架构更简洁,是未来方向。 我建议新项目直接上 KRaft,老项目可以逐步迁移。

3.6 部署时的几个坑

最后,分享几个我踩过的坑,希望能帮你省点时间:

  • 磁盘选择: 别用 NAS 或网络存储,Kafka 对磁盘延迟极其敏感。本地 SSD 是最佳选择。
  • 内存分配: Kafka 本身不占太多内存,但操作系统会拿剩余内存做 Page Cache。所以给 Kafka 留足系统内存,别把机器内存全部分给 JVM。
  • 网络带宽: 集群节点之间最好用万兆网络。千兆网络在数据量大的时候会成为瓶颈。
  • 监控先行: 部署完第一时间配上监控。我习惯用 Prometheus + Grafana,重点看 UnderReplicatedPartitions 和 RequestHandlerAvgIdlePercent 这两个指标。
一个小技巧: 部署前先用 fio 工具测一下磁盘的随机写性能。Kafka 的写入性能很大程度上取决于磁盘的 IOPS,而不是顺序读写速度。我曾经遇到过一块号称“高性能”的云盘,实际 IOPS 不到 2000,跑 Kafka 直接拉胯。