欢迎光临
我们一直在努力

Kafka 容错机制与死信队列实战

我是如何把 Kafka 从“能跑”改成“真能扛事”的

我一开始用 Kafka 的时候,其实心态很简单:

消息能消费,数据能落库,日志不红,就算稳了。

后来才知道,这种状态只能叫一句话:
没出事而已。

真正让我把 Kafka 当回事的,是一次主数据对接事故。


一、那天我才明白:Kafka 不怕报错,怕一直报同一个错

我们系统对接的是联通主数据平台,Kafka 作为唯一通道。

角色很明确:

  • 上游负责推

  • Kafka 负责存

  • 我们负责消费

某天凌晨,电话把我吵醒。

现象很诡异:

  • 服务没挂

  • Kafka 消费线程还活着

  • CPU、内存都正常

  • 但主数据就是不再往下走了

我一开始以为是 Kafka 抽风,后来翻日志才发现真相。


二、一条坏数据,把我整个消费者组拖死了

Kafka Topic 里混进来一条数据:

  • JSON 结构是对的

  • 但业务字段缺了一个必填值

  • 我代码里直接空指针

然后事情就开始失控了。

流程非常“合理”:

  • Kafka 拉到这条消息

  • 业务处理抛异常

  • offset 没提交

  • 下次 poll,还是这条

  • 再抛异常

  • 无限循环

  • 后果是:

    这条消息之后的所有正常数据,全被堵死。

    那一刻我才真正意识到一句话的含义:

    在 Kafka 里,一条消息不结束,后面的世界就不会开始。


    三、Kafka 的容错,本质不是“不出错”,而是“错了别拖全场”

    后来我复盘这次事故,结论其实很残酷:

    Kafka 并不关心你业务对不对。

    它只认一件事:

    • 你有没有提交 offset

    所以 Kafka 容错设计,核心只围绕三个问题:

  • 这条消息值不值得再试

  • 试几次算仁至义尽

  • 真不行了,我该把它放哪


  • 四、我做的第一件事:彻底禁止自动提交 offset

    我当时干的第一件事,不是加死信队列,而是把自动提交 offset 全部关掉。

    enable-auto-commit: false ack-mode: manual

    从那一刻开始,我给自己立了一条死规矩:

    只要业务没完整跑通,哪怕日志再好看,我也不提交 offset。

    我只在四个条件全部满足时才 acknowledge:

    • 解密成功

    • 数据校验通过

    • 数据库落库成功

    • 回调上游成功

    只要中间任何一步炸了,offset 一律不动。

    这是 Kafka 容错的底线。


    五、我意识到:有些失败,其实是“可以等等再试的”

    当然,我也很快发现一个问题:

    不是所有异常都该立刻判死刑。

    比如:

    • 数据库偶发连接超时

    • 网络抖了一下

    • 上游接口短暂 502

    这种错误,我要是直接把消息打进死信队列,那就是我自己的问题。

    所以我引入了有限重试机制。

    逻辑非常简单:

    • 消费失败

    • 等 10 秒

    • 再来一次

    • 最多 3 次

    这一步,解决的是临时性错误。

    但也正是在这里,我开始意识到一件更现实的事。


    六、我终于承认:有些消息,天生就是处理不了的

    随着系统跑久了,我发现了一类消息:

    • 重试 3 次还是炸

    • 重启服务还是炸

    • 换环境跑还是炸

    这时候我得承认:

    不是系统不努力,是这条数据真的有问题。

    如果我继续让 Kafka 卡在这条消息上,那等于用一条坏数据,绑架整个 Topic。

    所以我必须做一件事:

    给这些消息找个“善后去处”。


    七、死信队列,在我这里不是 Kafka 功能,是责任分界线

    我实现死信队列的时候,想得非常现实。

    它不解决问题本身,它只做一件事:

    把“系统处理不了的事”,交给人来处理。

    在我这套设计里,死信队列就是一张表。

    但这张表里,我坚持记录四类信息:

  • Kafka 元数据
    topic、partition、offset

  • 原始消息
    加密内容,长度

  • 异常信息
    异常类型、异常描述、完整堆栈

  • 处理状态
    待处理、处理中、成功、失败

  • 我当时给自己的要求只有一句话:

    半年后我再看这条死信,也要能还原事故现场。


    八、死信出现的那一刻,我做了一件关键的事

    当一条消息被判定进入死信队列时,我做了一件很多人会忽略的事:

    我提交了它的 offset。

    这是死信队列真正的意义。

    它不是“放着不管”,而是:

    用一条可追溯的记录,换 Kafka 继续往前跑。

    从那以后:

    • Kafka 不再被毒丸消息卡死

    • 后续正常数据可以继续消费

    • 我也能在白天,从容地处理这些异常数据


    九、死信队列不是垃圾桶,是事故记录仪

    我后来发现,死信队列最大的价值,根本不是“兜底”。

    而是:

    • 我知道系统哪里容易出问题

    • 我知道上游数据质量怎么样

    • 我知道哪些异常是代码问题,哪些是业务问题

    甚至有几次,死信队列比监控更早暴露问题。


    十、我现在对 Kafka 的一个判断

    现在再回头看这套 Kafka 设计,我给它的评价是:

    • 不追求不出错

    • 接受失败

    • 但绝不让失败拖垮系统

    如果你问我一句话总结 Kafka 容错和死信队列:

    Kafka 真正的成熟,不在于消息飞得多快,而在于出事时还能不能稳稳往前走。

    赞(0)
    未经允许不得转载:171主机测评 » Kafka 容错机制与死信队列实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址