博客
关于我
kafka no leader
阅读量:483 次
发布时间:2019-03-07

本文共 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日志分析

    进一步分析发现,Kafka日志文件中有大量主题索引文件损坏的警告信息。具体为offsetIndex.sanityCheck,显示索引文件中的_entries与_lastOffset与baseOffset的关系异常。在非正常退出的情况下,等到broker0节点重启,却无法正常恢复,双重问题叠加导致无法启动。

    代码逻辑解读

    sanityCheck逻辑解读

    • if (_entries == 0 || _lastOffset > baseOffset) { return true; } (翻译:如果_entries为空或者_lastOffset大于baseOffset,返回损坏的状态)

    这段代码量化地确定了索引文件的健康状况。如果_entries为空,说明没有索引文件内容,因此将其视为健康。否则,如果_lastOffset大于baseOffset,说明索引文件有损坏,需重建。

    问题可能原因

  • 非正常退出导致索引文件损坏:这导致在重启时无法及时跟上消息,进而影响Leader选举。

  • ISR库为空状态,无法复选Leader:由于leader副本在broker0,且其他副本已经移出ISR,无法自动重新选出Leader,导致分区无法正常运作。

  • Broker节点无法正常重启:由于在重启过程中,索引文件持续损坏或被重建,导致Broker节点无法重新启动,成为.docker process 挂 dropout 的一大因素。

  • 缺失与错误分析

    结合用户提供的JIRA问题分析,发现问题可能源于两个已知的Bug:

  • KAFKA-4972:在某些情况下,Kafka可能会在日志文件被删除或重建索引文件时,错误地判断索引文件损坏。

  • KAFKA-3955:涉及Broker在非正常退出后无法正确恢复,导致重启过程异常。

  • 解决思路

    基于以上分析,问题主要集中在:

  • Broker节点重启失败,导致无法为分区选出新的Leader。
  • 索引文件持续损坏,阻碍Node正常启动和分区恢复。
  • 解决方案:

  • 强制结束非正常退出节点:使用kill -9强制关闭broker0,此举解决了Node长时间无响应的问题,并允许Kafka重新启动。

  • 索引文件与日志文件的重建:在非正常退出后,自动生成删除旧的日志和索引文件,并在重启完成后进行重建。

  • 分区复苏策略

    • 手动设定副本作为temporary Leader:在34分区无法选出新的Leader时,可以临时手动将它们的数据同步到副本节点上,作为临时Leader,继续消息处理。但需要谨慎操作,避免数据不一致。
    • 分区迁移:如果确实存在数据不一致、无法恢复的情况,可以选择迁移分区的数据到其他副本上,初步解决领导权问题。
  • 升级Kafka版本:根据用户反馈,2022年之后的二次版本修复了这些Bug,升级至最新的稳定版本可以有效减少类似问题发生。

  • 优化Broker参数设置:检查并适当调整Broker的配置参数,如:

    • unclean.leader.election.enable=true:允许从非ISR副本选举新的Leader,以防止类似问题再次发生。
    • default.replication.factor=3:提高分区的副本数量,提高高可用性。
    • min.insync.replicas=2:确保至少有两个副本在同步状态,这样即使ISR副本失败,也可以从其他副本中选出新的Leader。
    • 为high.generation.wait Congressman调整时间间隔:避免因超时导致Broker进程无法正常结束。
  • 优化系统运行环境

    • 使用systemctl或其他工具优雅关闭节点:建议优先使用systemctl stop或类似命令而非kill -9,以允许Kafka进行优雅重启,减少非正常退出带来的问题。
    • 调整系统服务超时设置:在一些Linux系统中,默认的服务超时过短,导致Kafka无法及时完成关闭,进而引发非正常退出。使用systemctl edit broker命令,手动调整服务超时参数到更长值。
  • 后续集群优化策略

    • 定期检查并修复:频繁的节点重启可能导致日志文件及索引文件及时修复不上。定期自动化地检查日志和索引文件的状态,及时发现问题并触发修复。

    • 高可用性方案

      • 增加Broker节点数目,减少单点故障。
      • 配置ISR监控,及时发现ISR健康状态。
      • 引入负载均衡,分布式消费者的强化,以避免所有消息都落入同一分区。
    • 监控与告警系统

      • 配置完善的监控工具,如Prometheus、Grafana、ELK-stack等,实时监控Kafka集群状态,及时发现异常情况。
      • 建立高可用性的告警系统,能够在出现故障时自动触发通知或自动化处理流程。
    • 数据迁移计划

      • 对于重要的分区,定期进行数据迁移,确保在发生节点故障时,可以快速切换到其他副本,减少服务中断。
      • 开发自动化脚本进行数据迁移,减少人为错误,提高效率。
    • 优化消费者与生产者的配置

      • 检查生产者的ack设置,确保消息可靠到达。
      • 额外设置消费者的重试机制,处理消息暂留和不可用问题。
      • 优化分区分配策略,避免所有消息都命中同一分区,提升系统性能和可靠性。

    总结

    针对上述问题,本次排查主要关注以下几个方面:

  • 非正常退出的问题:在Kafka服务中,正常的停止更倾向于调用stop命令,而非使用kill -9。后者可能导致留下陈旧的资源状态,进而影响重启过程。

  • 重建索引文件的异常: 需要细化代码行为,确保在非正常退出时不会生搬硬套地认为索引文件损坏,导致持续拷贝。

  • ISR机制的处理:在高版本Kafka中,通过设置unclean.leader.election.enable=true可以有效避免当ISR为空时,依然能够选出新的Leader,这解决了当单个Brokers无法正常工作时不会阻止整个分区的可用性问题。

  • 版本升级的必要性:检测到此次问题的症状,那么在现存的版本中不应重现同样问题。在新版本中,可能已经修复了这些Bug,从而防止问题的重现。

  • 该次排查强调了日常运维和故障处理中的细节关注,也破坏了代码层面、配置层面与系统行为层面相结合的问题。在尚未熟练掌握Kafka源码分析的情况下,最高指导是及时升级版本并返回精准的现象描述,以便外部支持进一步资料对比和解决方案提供。

    转载地址:http://cefcz.baihongyu.com/

    你可能感兴趣的文章
    Netty源码—6.ByteBuf原理一
    查看>>
    Netty源码—6.ByteBuf原理二
    查看>>
    Netty源码—7.ByteBuf原理三
    查看>>
    Netty源码—7.ByteBuf原理四
    查看>>
    Netty源码—8.编解码原理一
    查看>>
    Netty源码—8.编解码原理二
    查看>>
    Netty源码解读
    查看>>
    Netty的Socket编程详解-搭建服务端与客户端并进行数据传输
    查看>>
    Netty相关
    查看>>
    Netty遇到TCP发送缓冲区满了 写半包操作该如何处理
    查看>>
    Netty:ChannelPipeline和ChannelHandler为什么会鬼混在一起?
    查看>>
    Netty:原理架构解析
    查看>>
    Network Dissection:Quantifying Interpretability of Deep Visual Representations(深层视觉表征的量化解释)
    查看>>
    Network Sniffer and Connection Analyzer
    查看>>
    Network 灰鸽宝典【目录】
    查看>>
    NetworkX系列教程(11)-graph和其他数据格式转换
    查看>>
    Networkx读取军械调查-ITN综合传输网络?/读取GML文件
    查看>>
    network小学习
    查看>>
    Netwox网络工具使用详解
    查看>>
    Net与Flex入门
    查看>>