本文共 3542 字,大约阅读时间需要 11 分钟。
Kafka 重启失败问题排查详述
在2022年2月10日下午,用户反馈Kafka集群A主题的34分区无法选举Leader,导致发送消息到该分区时出现“无论”错误。“In the middle of a leadership election, there is currently no leader for this partition and hence it is unavailable for writes.” 这一错误表明分区在领导选举过程中出现问题,无法为写入提供服务。
该问题首次出现在运维团队尝试重启broker0节点时。在非正常退出的情况下,Kafka在启动时会执行recover logs处理过程,其中包括调用sanityCheck方法检查log segment的索引文件完整性。用户报告中指出,这次操作导致大量主题索引文件损坏和重建索引文件的警告信息。
问题根源分析
非正常退出导致索引文件损坏:在非正常退出的情况下,Kafka会生成一个.kafka_cleanshutDown文件。启动时检测该文件的存在,如果不存在,则说明是非正常退出。为了恢复日志,recover logs将调用offsetIndex#sanityCheck方法,检查每个log segment的索引文件是否完整。
索引文件损坏原因:由于Kafka的索引文件是一个稀疏索引,采用entry模式存储,每条消息的位置不全部记录到索引文件中。这种结构设计导致entry数量计算为mapolisonformation的位置/entrySize。lastOffset是最后一块entry的位移,baseOffset是索引文件名称中的基偏移量。在旧版本中,若_entries == 0 || _lastOffset > baseOffset则表示索引文件损坏,需要重建。
ISR问题与Leader选举失败:在0.11版本中,unclean.leader.election.enable默认为false,意味着分区不可从ISR之外的副本选举新的Leader。在34分区的情况下,Leader副本位于broker0,而另一个副本由于速度跟不上被移出ISR。这导致在重启broker0时,分区无法重新选举Leader,进而无法恢复消息发送。
进一步分析发现,Kafka日志文件中有大量主题索引文件损坏的警告信息。具体为offsetIndex.sanityCheck,显示索引文件中的_entries与_lastOffset与baseOffset的关系异常。在非正常退出的情况下,等到broker0节点重启,却无法正常恢复,双重问题叠加导致无法启动。
sanityCheck逻辑解读:
这段代码量化地确定了索引文件的健康状况。如果_entries为空,说明没有索引文件内容,因此将其视为健康。否则,如果_lastOffset大于baseOffset,说明索引文件有损坏,需重建。
问题可能原因:
非正常退出导致索引文件损坏:这导致在重启时无法及时跟上消息,进而影响Leader选举。
ISR库为空状态,无法复选Leader:由于leader副本在broker0,且其他副本已经移出ISR,无法自动重新选出Leader,导致分区无法正常运作。
Broker节点无法正常重启:由于在重启过程中,索引文件持续损坏或被重建,导致Broker节点无法重新启动,成为.docker process 挂 dropout 的一大因素。
结合用户提供的JIRA问题分析,发现问题可能源于两个已知的Bug:
KAFKA-4972:在某些情况下,Kafka可能会在日志文件被删除或重建索引文件时,错误地判断索引文件损坏。
KAFKA-3955:涉及Broker在非正常退出后无法正确恢复,导致重启过程异常。
基于以上分析,问题主要集中在:
解决方案:
强制结束非正常退出节点:使用kill -9强制关闭broker0,此举解决了Node长时间无响应的问题,并允许Kafka重新启动。
索引文件与日志文件的重建:在非正常退出后,自动生成删除旧的日志和索引文件,并在重启完成后进行重建。
分区复苏策略:
升级Kafka版本:根据用户反馈,2022年之后的二次版本修复了这些Bug,升级至最新的稳定版本可以有效减少类似问题发生。
优化Broker参数设置:检查并适当调整Broker的配置参数,如:
优化系统运行环境:
systemctl stop或类似命令而非kill -9,以允许Kafka进行优雅重启,减少非正常退出带来的问题。systemctl edit broker命令,手动调整服务超时参数到更长值。定期检查并修复:频繁的节点重启可能导致日志文件及索引文件及时修复不上。定期自动化地检查日志和索引文件的状态,及时发现问题并触发修复。
高可用性方案:
监控与告警系统:
数据迁移计划:
优化消费者与生产者的配置:
针对上述问题,本次排查主要关注以下几个方面:
非正常退出的问题:在Kafka服务中,正常的停止更倾向于调用stop命令,而非使用kill -9。后者可能导致留下陈旧的资源状态,进而影响重启过程。
重建索引文件的异常: 需要细化代码行为,确保在非正常退出时不会生搬硬套地认为索引文件损坏,导致持续拷贝。
ISR机制的处理:在高版本Kafka中,通过设置unclean.leader.election.enable=true可以有效避免当ISR为空时,依然能够选出新的Leader,这解决了当单个Brokers无法正常工作时不会阻止整个分区的可用性问题。
版本升级的必要性:检测到此次问题的症状,那么在现存的版本中不应重现同样问题。在新版本中,可能已经修复了这些Bug,从而防止问题的重现。
该次排查强调了日常运维和故障处理中的细节关注,也破坏了代码层面、配置层面与系统行为层面相结合的问题。在尚未熟练掌握Kafka源码分析的情况下,最高指导是及时升级版本并返回精准的现象描述,以便外部支持进一步资料对比和解决方案提供。
转载地址:http://cefcz.baihongyu.com/