3. 集群核心配置故障:Broker配置错误、Topic配置不合理、Producer/Consumer配置问题
配置问题,说白了就是 Kafka 集群的「慢性病」。不像磁盘满了、进程挂了那么急,但一旦爆发,往往是大面积、难定位的。我处理过的线上事故里,至少有一半根子出在配置上。今天咱们就把 Broker、Topic、客户端这三层的常见坑过一遍。
核心观点:配置故障的排查顺序永远是「先 Broker、再 Topic、最后客户端」。别一上来就调 Producer 参数,先看看集群本身是不是健康的。
3.1 Broker 配置:集群的骨架不能歪
Broker 配置是地基。地基歪了,上面盖什么都白搭。我个人习惯,新集群上线前会逐项核对下面这几个参数。
3.1.1 基础网络与存储配置
| 参数名 | 常见错误值 | 推荐值 | 后果 |
|---|---|---|---|
listeners |
绑定 0.0.0.0 但未配安全组 | 内网 IP + 端口 | 公网暴露、被挖矿 |
log.dirs |
单块盘、无 RAID | 多块盘、每块独立目录 | 单盘故障导致集群不可用 |
num.network.threads |
默认 3(32核机器) | CPU 核数 | 网络吞吐瓶颈 |
num.io.threads |
默认 8(磁盘阵列) | CPU 核数 * 2 | 磁盘 I/O 排队严重 |
我曾经遇到过一个案例:某团队把 log.dirs 配成了单块 SSD 的一个分区,结果那块盘写满了,整个集群所有 Topic 全部不可写。嗯,这就是典型的「单点故障」——虽然 Kafka 本身是分布式的,但配置没做好,照样挂。
3.1.2 副本与 ISR 配置
这里有个参数特别容易踩坑:min.insync.replicas。你想想看,如果这个值设成 1,那跟没设有什么区别?Leader 挂了数据就丢。
警告:min.insync.replicas 必须配合 Producer 的 acks=all 使用。单独设 Broker 端没用,Producer 端不认,数据该丢还是丢。
default.replication.factor:建议 3,别偷懒设成 1 或 2。我见过设成 2 的集群,一台 Broker 滚动重启,另一台网络抖动,瞬间只剩 1 个副本在线,写入直接报错。unclean.leader.election.enable:默认 false 是对的。设成 true 虽然能快速恢复 Leader,但会丢数据。除非你明确知道自己在做什么,否则别动。
3.1.3 日志保留与清理
很多运维同学喜欢把 log.retention.hours 设得特别大,比如 168 小时(7天)。但磁盘空间是有限的。我建议按业务需求来,别一刀切。
| 参数 | 典型误配置 | 正确做法 |
|---|---|---|
log.retention.bytes |
不设,只按时间保留 | 时间和空间双重限制,谁先到算谁 |
log.segment.bytes |
默认 1GB 不改 | 高频写入场景可调小到 256MB |
log.cleaner.threads |
默认 1 | CPU 核数 / 2,至少 2 |
技巧:如果你发现磁盘使用率持续上涨但日志清理没生效,先检查 log.cleaner.backoff.ms 是不是太大(默认 15 秒),以及 log.cleaner.io.max.bytes.per.second 是否限制了清理速度。
3.2 Topic 配置:别让业务方乱建 Topic
Topic 配置不合理,往往是业务方直接建 Topic 导致的。我建议运维团队把 Topic 创建权限收回来,统一管理。
3.2.1 分区数:不是越多越好
分区数 = 并行度。但分区太多也有副作用:文件句柄暴增、Leader 选举变慢、客户端内存开销大。
- 经验公式:分区数 ≈ max(Producer 并发数, Consumer 并发数) * 2
- 上限建议:单 Broker 分区数不超过 2000,整个集群不超过 10000
我在项目中遇到过一个极端案例:业务方建了一个 500 分区的 Topic,集群总共 3 台 Broker,每台 Broker 要管理 160 多个分区。结果一次 Broker 重启,Leader 选举花了 40 多秒,期间整个 Topic 不可用。
3.2.2 副本因子:别省这个钱
副本因子设成 1 的 Topic,我建议直接拒绝上线。你想想看,一台 Broker 挂了,这个 Topic 的数据就全丢了。省那点磁盘空间,不值当。
| 场景 | 推荐副本数 | 说明 |
|---|---|---|
| 生产核心链路 | 3 | 容忍 2 台 Broker 同时故障 |
| 日志/监控 | 2 | 可容忍 1 台故障,允许少量丢数据 |
| 测试/开发 | 1 | 无所谓,丢了重建 |
3.2.3 消息保留策略:按需配置
别所有 Topic 都用默认的 7 天保留。有些业务数据 1 小时后就没用了,有些需要保留 30 天。
建议:为每个 Topic 单独设置 retention.ms 和 retention.bytes。运维平台应该提供 Topic 配置模板,业务方只能选模板,不能自定义参数。
3.3 Producer/Consumer 配置:客户端才是大头
说实话,大部分 Kafka 性能问题出在客户端。Broker 和 Topic 配置好了,客户端配不对,照样崩。
3.3.1 Producer 常见配置问题
| 参数 | 错误配置 | 正确配置 | 后果 |
|---|---|---|---|
acks |
0 或 1 | all(配合 min.insync.replicas) | 数据丢失 |
buffer.memory |
默认 32MB | 64MB ~ 256MB(高吞吐场景) | 频繁阻塞、发送超时 |
compression.type |
none | snappy 或 lz4 | 网络带宽浪费 |
max.request.size |
默认 1MB | 根据消息大小调整(如 10MB) | 大消息发送失败 |
我曾经帮一个团队排查过 Producer 频繁超时的问题。他们配了 acks=all,但 max.in.flight.requests.per.connection 设成了 5。结果 Broker 端副本同步慢,Producer 端积压了 5 个未确认的请求,后面的请求全部超时。解决方案很简单:把这个值改成 1,或者开启幂等性。
3.3.2 Consumer 常见配置问题
Consumer 的问题更隐蔽,因为很多时候不是「不能用」,而是「用着用着就慢了」。
enable.auto.commit:默认 true。生产环境建议改成 false,手动提交。否则 Consumer 挂了,offset 可能没提交,重启后重复消费大量数据。max.poll.records:默认 500。如果单条消息处理时间很长(比如 1 秒),500 条就要处理 500 秒,远超max.poll.interval.ms(默认 5 分钟),Consumer 会被踢出消费组。session.timeout.ms:默认 45 秒。如果 Consumer 处理慢,可以适当调大,比如 60 秒或 90 秒。
警告:Consumer 的 group.id 不要重复使用。不同业务线的 Consumer 用同一个 group.id,会导致分区分配混乱,消息被抢来抢去。
3.4 配置故障排查流程图
下面这张图是我自己总结的配置故障排查路径。遇到问题,按这个顺序走一遍,基本能定位 90% 的问题。
3.5 避坑指南:我踩过的那些坑
最后分享几个真实案例,希望能帮你少走弯路。
案例1:某次大促,Producer 突然报 NotLeaderForPartitionException。排查发现,是因为 Topic 分区数从 10 扩到 20 后,部分分区的 Leader 还没完成迁移,Producer 的 metadata 缓存过期了。解决方案:Producer 端调小 metadata.max.age.ms(默认 5 分钟,改成 30 秒)。
案例2:Consumer 消费越来越慢,最后完全卡住。检查发现 max.poll.records 设成了 5000,但每条消息处理需要 200ms,一轮 poll 要处理 1000 秒,远超 max.poll.interval.ms(5 分钟)。Consumer 被踢出消费组,然后重平衡,再踢出,死循环。解决方案:调小 max.poll.records 到 500,或者调大 max.poll.interval.ms 到 15 分钟。
我曾经还遇到过一个更隐蔽的问题:Producer 的 retries 设成了 Integer.MAX_VALUE,结果 Broker 端磁盘满了,Producer 一直在重试,把网络带宽打满了。嗯,重试不是万能的,该限流的时候要限流。
配置问题,说白了就是「细节决定成败」。每个参数背后都有它的设计意图,别乱改,也别不改。希望今天的内容能帮你少踩几个坑。