一、消息队列(Kafka)故障诊断全景图

说实话,Kafka 在生产环境里出问题,翻来覆去就那么几类。我做了这么多年中间件运维,遇到最多的就是 Broker 挂了、分区 Leader 选不出来、消费者组 Rebalance 异常,还有消息积压。今天咱们就把这四类问题掰开揉碎,讲讲怎么诊断、怎么恢复。

核心思路:先定位症状,再分析根因,最后给出恢复策略。别一上来就重启,那是新手干的事。

Kafka 故障诊断 Broker 宕机 Leader 选举失败 Rebalance 异常 消息积压 诊断方法 恢复策略

二、Broker 宕机:最基础也最头疼的问题

2.1 怎么判断 Broker 真的挂了?

别光看监控面板变红就慌了。我习惯先跑几个命令确认一下:

# 查看集群中所有 Broker 状态
./kafka-broker-api-versions.sh --bootstrap-server localhost:9092

# 查看特定 Broker 是否在 ZK 中注册
./zookeeper-shell.sh localhost:2181 ls /brokers/ids

# 查看 Controller 是谁
./zookeeper-shell.sh localhost:2181 get /controller

嗯,这里要注意:如果 ZK 里能看到 Broker ID,但客户端连不上,那可能是网络问题,不一定是 Broker 挂了。

2.2 宕机后的连锁反应

Broker 一挂,影响是链式的:

  • 分区 Leader 重新选举 —— 这个我们后面细说
  • 生产者和消费者连接断开 —— 客户端会报连接异常
  • 副本同步滞后 —— 如果挂的是 Leader,Follower 需要追上进度
  • 消息可能丢失 —— 如果 acks=0 或 acks=1,没来得及刷盘的消息就没了

避坑指南:我曾经遇到过一台 Broker 的磁盘写满了,但进程还在。监控显示 Broker 活着,但所有分区都报错。所以别只看进程存活,要检查磁盘、网络、文件描述符这些底层资源。

2.3 恢复策略

场景 恢复操作 注意事项
进程异常退出 检查日志 → 修复配置 → 重启 先看 server.log 和 gc.log
磁盘故障 更换磁盘 → 从副本恢复数据 确保有至少一个 ISR 副本
内存溢出 调整 JVM 参数 → 重启 建议 -Xmx 不超过物理内存的 50%
网络分区 检查网络设备 → 恢复连通性 Broker 会自动重新加入集群

三、分区 Leader 选举失败:集群的「脑死亡」

说白了,分区没有 Leader,就像军队没有指挥官。生产者和消费者都找不到写入和读取的目标。

3.1 为什么会选举失败?

我总结了几种常见原因:

  1. ISR 列表为空 —— 所有副本都挂了,或者都落后太多
  2. Controller 挂了 —— 选举是由 Controller 触发的
  3. ZK 会话过期 —— Broker 和 ZK 失联了
  4. 网络抖动 —— 选举过程中网络不稳定

3.2 诊断命令

# 查看分区状态
./kafka-topics.sh --describe --topic my-topic --bootstrap-server localhost:9092

# 查看 Controller 状态
./kafka-leader-election.sh --bootstrap-server localhost:9092 --election-type preferred --topic my-topic --partition 0

# 查看 ZK 中分区信息
./zookeeper-shell.sh localhost:2181 get /brokers/topics/my-topic/partitions/0/state

个人经验:有一次我发现某个分区一直选不出 Leader,查了半天发现是 ZK 里该分区的状态数据损坏了。手动删除 ZK 节点后,Kafka 自动重建了分区状态。当然,这招有风险,建议先备份。

3.3 手动干预选举

如果自动选举失败,可以手动指定:

# 手动触发 Leader 选举
./kafka-leader-election.sh --bootstrap-server localhost:9092 \
  --election-type unclean \
  --topic my-topic \
  --partition 0

注意:unclean 选举会选一个不在 ISR 中的副本当 Leader,可能导致数据丢失。我一般只在「丢数据比不可用好」的场景下才用这招。

四、消费者组 Rebalance 异常:最隐蔽的坑

Rebalance 本身不是坏事,但频繁 Rebalance 或者 Rebalance 卡住,那就是问题了。你想想看,消费者们正在愉快地消费,突然全部停下来重新分配分区,这期间消息就积压了。

4.1 常见异常表现

  • 频繁 Rebalance —— 几分钟一次,甚至几秒一次
  • Rebalance 超时 —— 消费者无法在规定时间内完成分区分配
  • 消费者被踢出组 —— session.timeout.ms 内没发心跳
  • 分区分配不均匀 —— 有的消费者忙死,有的闲死

4.2 诊断方法

# 查看消费者组状态
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --group my-group --describe

# 查看消费者组详情(包括每个消费者的分区分配)
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --group my-group --describe --members --verbose

# 查看 Rebalance 相关日志
grep "Rebalance" /var/log/kafka/consumer.log | tail -100

4.3 根因分析

现象 可能原因 解决方案
频繁 Rebalance 消费者处理太慢,心跳超时 增大 max.poll.interval.ms 或优化处理逻辑
Rebalance 超时 分区数太多,消费者数太多 增大 rebalance.timeout.ms
消费者被踢出 网络抖动,GC 停顿 增大 session.timeout.ms,优化 GC
分配不均匀 使用了 Range 分配策略 改用 RoundRobin 或 Sticky 策略

我的经验:有一次线上频繁 Rebalance,查了半天发现是一个消费者的 GC 停顿太长,导致心跳超时。调整了 -Xmx 和 GC 算法后,问题解决。说白了,很多 Rebalance 问题根子在 JVM 上。

五、消息积压排查:从源头到终点

消息积压是最直观的问题——消费者跟不上生产者了。但积压的原因可能千奇百怪。

5.1 积压的几种类型

  1. 生产者侧积压 —— 生产速度远大于消费速度
  2. 消费者侧积压 —— 消费者处理能力不足
  3. 网络积压 —— 带宽不够,数据传输慢
  4. 磁盘积压 —— 磁盘 I/O 成为瓶颈

5.2 排查命令

# 查看每个分区的 Lag
./kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
  --group my-group --describe

# 查看 Topic 的写入速率
./kafka-run-class.sh kafka.tools.JmxTool \
  --object-name kafka.server:type=BrokerTopicMetrics,name=MessagesInPerSec

# 查看消费者消费速率
# 在消费者端打印每秒处理的消息数

5.3 恢复策略

我一般按这个优先级处理:

  • 扩容消费者 —— 增加消费者实例,注意分区数要够
  • 优化消费逻辑 —— 批量处理、异步处理、减少外部调用
  • 调整分区数 —— 增加分区数提高并行度
  • 限流生产者 —— 如果下游实在扛不住,只能让上游慢点
  • 临时跳过积压消息 —— 重置 offset 到最新位置(会丢消息,慎用)

避坑指南:我曾经为了快速解决积压,直接给 Topic 加了 10 个分区。结果消费者组 Rebalance 了 5 分钟,积压更严重了。所以扩容前一定要评估 Rebalance 的影响。

六、总结:故障诊断的「三板斧」

做了这么多年,我总结了一套通用的诊断流程:

  1. 看日志 —— server.log、controller.log、consumer.log,日志里啥都有
  2. 看监控 —— 磁盘、网络、CPU、内存、GC,一个都不能少
  3. 看指标 —— Lag、吞吐量、请求延迟、连接数

嗯,其实大部分问题都能在这三步里找到答案。如果还找不到,那就看看是不是 ZK 的问题——很多 Kafka 的「疑难杂症」,根子都在 ZK 上。

最后说一句:别怕出问题,怕的是出了问题不知道怎么查。把这四类问题的诊断方法记熟了,Kafka 运维你就入门了。

专注资料整理