Kafka 是大数据领域的事实标准消息中间件,日志采集、实时计算、事件溯源、数据同步都靠它。但它跟 RabbitMQ 这类"业务消息队列"的定位差别很大:Kafka 是为高吞吐、可持久化、可回放的流式数据设计的,一台机器几万到几十万条每秒是常态。正因如此,Kafka 集群的规划思路也完全不同——它最吃的是磁盘和网络,CPU 常常不是瓶颈,内存主要用来做页缓存而不是堆。
这篇文章面向要自己规划 Kafka 集群的运维和架构人员,把组件概念、分区与并行度、副本与可靠性、磁盘、内存、网络带宽逐项讲清楚,最后给出按吞吐选配置的经验值。ZooKeeper 和 KRaft 两种元数据模式的差异也一并说明。
一、Kafka 的核心组件
先建立正确的概念模型。
- Broker:一个 Kafka 服务节点,多个 broker 组成集群。每个 broker 有唯一 id。
- Topic:消息的逻辑分类,类似"表"或"频道"。生产者往 topic 写,消费者从 topic 读。
- Partition(分区):topic 的物理切分,是最小并行单位。消息在分区内有严格顺序,跨分区不保证顺序。分区可以分布在不同的 broker 上,这是 Kafka 能横向扩展的根本原因。
- Replica(副本):每个分区有若干副本,分布在不同的 broker 上,其中一个是 leader,其余是 follower。读写只经过 leader,follower 负责同步。
- Controller:集群里有一个 broker 担任 controller,负责管理分区 leader 选举、副本分配等元数据操作。
- ISR(In-Sync Replicas):与 leader 保持同步的副本集合。只有 ISR 里的副本才有资格在 leader 挂掉后成为新 leader。
- Offset(偏移量):消息在分区内的序号,消费者靠它记录消费进度。
理解"分区是并行单位"这一点最关键:topic 的吞吐上限取决于分区数,消费者组的并行度上限也等于分区数。所以分区数是规划的核心参数。
二、ZooKeeper 与 KRaft:两种元数据模式
早期 Kafka 依赖 ZooKeeper 存储集群元数据(broker 注册、topic 配置、分区 leader 信息、controller 选举等)。从 Kafka 2.8 起引入了 KRaft 模式(Kafka Raft),把元数据管理内置到 Kafka 自己,不再依赖 ZooKeeper;从 Kafka 3.3 起 KRaft 达到生产可用,Kafka 4.0 则彻底移除了 ZooKeeper。
两者对比:
| 维度 | ZooKeeper 模式 | KRaft 模式 |
|---|---|---|
| 外部依赖 | 需要额外部署 ZK 集群 | 无外部依赖,元数据内置 |
| 部署复杂度 | 两套系统,运维成本高 | 一套系统,明显简化 |
| 元数据规模 | ZK 存储,元数据大时受限 | 支持更大规模元数据 |
| 选主机制 | ZK 协调 | Raft 协议 |
| 版本要求 | 所有版本 | 3.3+ 生产可用,4.0 起唯一模式 |
| 适用建议 | 存量集群 | 新集群一律选 KRaft |
结论很直接:新部署优先用 KRaft,少维护一个 ZooKeeper 集群,故障点更少。存量集群可以按官方迁移流程逐步切到 KRaft。下面的规划内容对两种模式都适用,只在元数据节点相关处会有区别。
三、分区数与并行度
分区数决定了 topic 的最大并行度和吞吐上限,但不是越多越好。
怎么定分区数? 从两个方向取较大值:
一是吞吐。单个分区能承载的吞吐是有限的(经验上单分区每秒几 MB 到十几 MB,视硬件和消息大小而定,比如 10MB/s 是一个常见参考量级)。目标吞吐除以单分区吞吐,大致就是要的分区数。
二是消费者并行度。如果消费者组最多需要 N 个并发消费实例,分区数至少要是 N,否则多余的消费者会空闲。
同时要注意上界:分区太多会带来额外开销——每个分区在 broker 上对应文件句柄、内存缓冲、以及元数据;分区过多会增加 leader 选举和 rebalance 的时间。经验上单 broker 承载的分区数控制在几千以内比较稳妥(比如 2000 到 4000,视规格而定),超大规模集群不建议盲目堆分区。
还要注意:分区数只能增加,不能减少(减少需要重建 topic 或用工具搬迁)。增加分区会破坏按 key 的顺序保证,因为同一 key 的消息可能因为分区数变化而落到不同分区。所以建 topic 时宁可多留一点余量。一个常用折中:按当前需求的 2 到 3 倍预留,但不夸张。
四、副本数与可靠性
副本数是可靠性和成本之间的直接权衡。
replication.factor=1:只有一份数据,broker 挂了数据可能丢,仅适合可丢数据的场景。replication.factor=2:能容忍一个副本挂,但可用性一般。replication.factor=3:生产环境的标准配置,能容忍一个 broker 故障而不丢数据、不中断服务。
生产环境建议:副本数 3,min.insync.replicas=2,配合生产者 acks=all。这三者组合的含义是:消息要写入到至少 2 个副本才算成功,即使挂掉一个 broker 也不会丢数据,也不会因为副本不足而拒绝写入。这是可靠性配置的黄金三角。
# broker 端默认值(server.properties)
default.replication.factor=3
min.insync.replicas=2
unclean.leader.election.enable=false # 禁止非 ISR 副本当选 leader,避免丢数据
// 生产者端
acks=all
retries=Integer.MAX_VALUE
enable.idempotence=true
关于 unclean.leader.election.enable:设为 true 时,允许不在 ISR 里的副本(即数据落后的副本)当选 leader,好处是可用性高(分区能快速恢复可用),坏处是可能丢数据。金融、订单这类不能丢数据的场景应设为 false。
副本数提高会增加磁盘、网络和 CPU 开销(follower 要同步数据),所以副本数和 broker 数要协调:副本数不能超过 broker 数(否则副本无处分配),三副本集群最好至少 3 个 broker,考虑运维余量建议 4 到 5 个。
五、磁盘:Kafka 最关键的资源
如果只能优化一项资源,Kafka 选磁盘。
Kafka 的写入是纯顺序追加,这是它能用机械盘也能跑出高吞吐的原因——顺序写在 HDD 上就能达到上百 MB/s。而它的读取往往也能命中页缓存,或者按顺序从磁盘读。所以 Kafka 对磁盘的随机 IOPS 要求相对低,但对容量、顺序写带宽、以及磁盘数量有要求。
磁盘选型经验:
- 机械盘(HDD):性价比高,顺序写足够,适合吞吐型、大容量、冷数据多的场景。
- SSD/SATA SSD:延迟更低,适合对延迟敏感的场景,或 topic 数量多、并发请求高时。
- NVMe:性能最好,成本最高,适合极致低延迟或高并发场景。
容量规划公式(经验值):
单副本数据量 = 日增数据量 × 保留天数
总磁盘需求 = 单副本数据量 × 副本数 × (1 + 预留比例)
举例:日增 100GB,保留 7 天,副本 3,预留 30%:
100GB × 7 = 700GB(单副本),× 3 = 2100GB,× 1.3 ≈ 2730GB。也就是约 3TB 可用空间,若用 2TB 盘做 RAID 或 JBOD,要规划到 4TB 以上。
关于保留策略,三种方式可组合:
# 按时间保留(最常用)
log.retention.hours=168 # 7 天
# 按容量保留(超出后删最旧的段)
log.retention.bytes=107374182400 # 单分区 100GB,注意是每分区
# 按日志段大小滚动
log.segment.bytes=1073741824 # 1GB
风险提示:Kafka 按保留策略删除数据是不可逆的。调小
log.retention.hours或log.retention.bytes之后,超出范围的数据会被后台线程删除,一旦删除无法恢复。调整保留策略前要确认下游消费进度,避免删掉还没被消费的数据。设置log.retention.bytes时尤其注意它作用在每个分区上,写小数值(比如以为是全局)可能导致数据被迅速清空。
磁盘布局上,Kafka 会把每个分区的一个日志段写到一个目录。用多块盘分担(log.dirs 配多个目录)能提升总 IO 带宽。多盘可以做成 RAID 0(追求吞吐、不冗余,靠 Kafka 副本保可靠性)或 JBOD。一般不推荐 RAID 5/6,写入放大会拖累性能。
六、内存:给页缓存,不是给堆
Kafka 的内存规划有个反直觉的点:Kafka broker 本身不需要大堆,操作系统页缓存才是性能关键。
Kafka 的读写大量依赖操作系统的 page cache:生产者写入的数据先进 page cache,由操作系统刷盘;消费者读取近期数据时命中 page cache 就不用碰磁盘。所以内存的主要用途是当缓存,而不是 JVM 堆。
建议:JVM 堆设 6GB 到 8GB 就足够(经验值,很多生产集群用 6GB),把其余内存尽量留给操作系统做 page cache。堆太大反而会因为 GC 停顿影响 broker 稳定,而且堆里的数据无法被操作系统当缓存复用。
# 环境变量或启动脚本中设置
export KAFKA_HEAP_OPTS="-Xmx6G -Xms6G"
# 或新版 kafka-server-start.sh 里通过 KAFKA_HEAP_OPTS
所以一台 64GB 内存的 broker,堆设 6GB,剩下约 58GB 给页缓存和系统,这种配置很常见。不要把 64GB 里 32GB 给堆。
其他内存相关:num.io.threads(磁盘 IO 线程,一般设为核心数)、num.network.threads(网络线程,默认 3,高并发可调大)、socket.send.buffer.bytes、socket.receive.buffer.bytes(可用默认)。
七、CPU
相比磁盘和内存,Kafka 对 CPU 的要求没那么高,但也不能忽视。
CPU 主要消耗在:消息压缩解压(如果开启压缩)、网络收发、以及副本同步。压缩率越高、消息越大,CPU 消耗越大。所以如果开了 compression.type=lz4 或 zstd,要预留更多 CPU。
建议:8 核到 16 核是常见的生产配置(经验值)。核心数不宜过多,因为线程模型的关系,过多核心收益递减。如果 broker 上还跑别的服务,要单独评估。
另外一提,Kafka 4.0 的 KRaft controller 节点也消耗少量 CPU,但专用 controller 一般用较小规格即可。
八、网络带宽估算
带宽经常是 Kafka 集群的第一个瓶颈。原因很简单:三副本复制意味着写入一份数据要在网络上传三份(leader 收一次,再发给两个 follower)。再算上消费者拉取:如果是下游消费,出口带宽等于消费吞吐。
所以保守估算总带宽:
写入侧带宽 ≈ 生产吞吐 × 副本数
读取侧带宽 ≈ 消费吞吐
总带宽需求 ≈ 写入侧 + 读取侧,再留 30%~50% 余量
举例:生产 200MB/s,副本 3,则写入侧约 600MB/s;若消费也是 200MB/s,总需求约 800MB/s,加余量要按 1Gbps 到 2Gbps 以上规划。注意这里的 MB/s 和 Mbps 换算:1 字节等于 8 比特,600MB/s ≈ 4.8Gbps,所以千兆网卡明显不够,需要万兆(10GbE)。这是很多新手规划时最容易低估的地方。
建议生产 broker 用 10GbE 或更高网卡,并把 broker 间的复制流量和客户端流量在网络上尽量隔离(不同网卡或 VLAN),避免互相挤占。
九、按吞吐选配置(经验值)
下面给出一套经验参考,实际以压测为准。假设消息大小 1KB 左右、副本 3、开启 lz4 压缩。
| 吞吐量级 | broker 数 | 单 broker 规格 | 说明 |
|---|---|---|---|
| < 10MB/s | 3 | 4~8 核 / 16GB / 2×SSD | 开发到中小业务 |
| 10~50MB/s | 3~5 | 8 核 / 32GB / 多块 SSD | 中等规模日志/事件 |
| 50~150MB/s | 5~10 | 12~16 核 / 64GB / 多块 NVMe | 大型数据管道 |
| > 150MB/s | 10+ | 16 核 / 64~128GB / 高速 NVMe | 需要压测和精细调优 |
对应的关键配置:
| 资源 | 关键项 | 经验值 |
|---|---|---|
| 堆内存 | KAFKA_HEAP_OPTS | 6~8GB,其余留给页缓存 |
| 磁盘 | log.dirs | 多块盘分担,SSD/NVMe 更佳 |
| 副本 | replication.factor / min.insync.replicas | 3 / 2 |
| 分区 | num.partitions(默认)/ 按 topic 定 | 按吞吐和并行度算,单 broker 数千以内 |
| 网络 | 网卡 | 10GbE 起 |
| 线程 | num.io.threads / num.network.threads | IO 线程≈核数,网络线程 3~8 |
十、部署前后的检查与监控
部署后确认集群状态:
# 查看 topic 详情(分区、副本、ISR)
kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic mytopic
# 列出所有 topic
kafka-topics.sh --bootstrap-server localhost:9092 --list
# 查看消费者组堆积
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group mygroup
# 查看 broker 与 controller
kafka-broker-api-versions.sh --bootstrap-server localhost:9092
必须监控的指标:
- 消费滞后(consumer lag):
kafka-consumer-groups里的 LAG,持续增长说明消费跟不上。 - ISR 收缩:ISR 数量下降说明有副本落后,可靠性风险上升。
- Under-Replicated Partitions(URP):非零说明有分区副本不同步。
- 磁盘使用率与 IO:接近水位要提前扩容或调整保留。
- 网络带宽利用率:持续高位说明要加带宽或加 broker。
- GC 时间:堆设得合理时应该很低,频繁 Full GC 要警惕。
常见问题
Q:分区越多吞吐越高吗?
不完全是。分区增加能提升并行度,但每个分区有固定开销,过多会拖慢 rebalance 和 leader 选举。按吞吐和消费并行度取够用即可,单 broker 控制在数千以内。
Q:为什么我的 Kafka 集群会丢数据?
多半是配置问题:副本数 1、min.insync.replicas 太小、生产者 acks 不为 all、或 unclean.leader.election.enable=true。按"副本 3 + min.insync.replicas 2 + acks=all"配齐再排查。
Q:Kafka 用机械盘行不行?
可以。Kafka 是顺序写,HDD 顺序吞吐不差,适合大容量低成本场景。如果延迟敏感或并发高,再上 SSD/NVMe。
Q:堆设大一点不是更好吗?
不是。Kafka 靠操作系统页缓存加速,堆太大会挤占缓存、增加 GC 停顿,反而更差。6GB 到 8GB 堆配合大内存是很常见的生产配置。
Q:ZooKeeper 和 KRaft 该选哪个?
新集群选 KRaft,省一套系统、少一个故障点。存量 ZooKeeper 集群可评估后迁移。
Q:网络要多大?
按"生产吞吐 × 副本数 + 消费吞吐"估算并留余量。要注意 MB/s 与 Mbps 的 8 倍换算,很多吞吐型的集群千兆网卡根本不够,需要万兆。
总结
- 分区是 Kafka 的并行单位,吞吐上限和消费并行度都由它决定,按需求算但要控制总量,且分区只能增不能减。
- 生产可靠性黄金配置是副本数 3、
min.insync.replicas=2、生产者acks=all,并把unclean.leader.election.enable设为 false。 - 磁盘是最关键的资源,按"日增 × 保留天数 × 副本数 + 预留"做容量规划,多盘分担,注意保留策略不可逆。
- 内存给页缓存而不是堆,堆设 6GB 到 8GB 即可,大内存优先留给操作系统。
- 网络最容易成为瓶颈,按"写入侧 × 副本数 + 读取侧"估算并留余量,生产用万兆网卡。
- 新集群优先用 KRaft,监控重点看消费滞后、ISR 收缩、URP、磁盘和带宽。
企业QQ咨询




