Kafka的死信队列

Kafka本身没有内置死信队列 ,死信队列是业务层面的设计方案:消费失败、无法正常处理的消息,转发到专门的死信 Topic,不再重复重试消费,避免阻塞消费。

一、什么时候消息进死信

常见场景:

  1. 业务异常:消息格式错误、数据非法、缺少字段,无论重试多少次都处理失败(不可恢复错误)
  2. 重试次数耗尽:重试 N 次后仍然失败,不再继续重试
  3. 超时、消息内容损坏、反序列化失败

区分:临时故障(数据库短暂不可用)→ 重试;数据本身坏了 → DLQ

二、核心架构(经典链路)

复制代码
原始Topic → Consumer消费
    ↓
消费失败
    ├─可重试异常 → 发送到【重试Topic】,延迟一段时间后重新消费
    └─不可重试异常 / 重试次数用完 → 发送到【死信Topic(DLQ)】
  • 原始 Topic:正常业务消息
  • 重试 Topic:用来做延迟重试(可以多个,按重试轮次拆分)
  • DLQ Topic:存放彻底失败消息,不再自动消费,人工排查

Kafka 没有延迟消息,重试一般两种实现:

  1. 单重试 Topic + 消费时 sleep(简单,不推荐高吞吐)
  2. 多个重试 topic,不同延时,定时轮询(主流方案)

三、实现思路(Consumer 侧)

  1. 消费消息,执行业务逻辑
  2. try-catch 捕获异常
    • 如果是可重试异常:记录重试次数,发到重试 Topic
    • 如果是不可重试异常,或者重试次数 ≥ 阈值:发送到 DLQ
  3. 提交 offset(重点! ) ✅ 必须提交 offset,否则这条消息会无限重放,阻塞整个消费分区 很多新手坑:不提交 offset,消息一直卡在原始队列反复抛错

伪代码示意

复制代码
while (true) {
    ConsumerRecords records = consumer.poll();
    for (ConsumerRecord record : records) {
        try {
            process(record); //业务处理
        } catch (BusinessException e) {
            // 不可恢复异常,转入DLQ
            sendToDLQ(record);
        } catch (DBTempException e) {
            //临时异常,重试
            int retryCount = getRetryCount(record);
            if(retryCount < 3){
                sendToRetryTopic(record, retryCount+1);
            }else{
                sendToDLQ(record);
            }
        }
        consumer.commitSync(); //提交offset,原始消息不再拉取
    }
}

四、DLQ Topic 设计要点

  1. 分区数:建议和原 topic 分区数保持一致,或者根据死信量单独评估
  2. 消息保留时间:设置更长保留时长(比如 7 天),方便排查,到期自动清理
  3. 消息附加元数据(非常重要) 转发到 DLQ 时,不要只转发原始消息体 ,额外带上 header:
    • 原 topic、分区、offset
    • 失败时间、异常堆栈
    • 重试次数
    • 消息产生时间 方便定位是哪条消息、什么时候失败
  4. 消费隔离:死信 Topic 单独消费,不能和业务 consumer 共用 死信一般人工消费、导出、审计、修复后重放,不自动回写业务。

五、常见坑

  1. ❌ 忘记提交 offset → 消息无限重试,消费卡死
  2. ❌ 死信不带元数据 → 出问题找不到原始上下文
  3. ❌ 所有异常一律丢 DLQ:临时故障也直接丢,消息丢失
  4. ❌ DLQ 不做监控:死信堆积没人发现,故障延迟很久才感知

建议监控:DLQ 消息数量,一旦新增消息触发告警

六、框架内置支持

很多框架封装好了 DLQ,不用自己写转发逻辑:

  • Spring Kafka:DeadLetterPublishingRecoverer,配置重试、死信
  • Flink Kafka Consumer、Spark Streaming 也提供 DLQ 配置
  • 原生 Kafka 客户端:需要自己编码实现转发

七、死信消息后续怎么处理

  1. 监控告警:DLQ 有消息触发告警
  2. 排查:读取死信消息 + 异常信息定位 bug
  3. 修复数据 / 代码后:
    • 方案 1:写工具消费 DLQ,修复后重新投递到原始 topic
    • 方案 2:人工补发
相关推荐
RobinXYuan2 天前
【Kafka 源码手记】02 Kafka 的核心哲学:Everything Is A Log
kafka·源码阅读
Sayai2 天前
Kafka 2.8→3.9.1 跨大版本升级实战:ZooKeeper 同步升级、数据目录迁移与回滚预案全流程
大数据·运维·分布式·zookeeper·kafka
guo_wen_qiang4 天前
kafka重复消费
分布式·kafka
ClouGence5 天前
开源数据库管理工具 CloudDM 4.4.0 发布,新增 Kafka、SAP HANA 数据源
数据库·kafka
RobinXYuan5 天前
【Kafka 源码手记】01 从消息队列到 Event Streaming
kafka·源码阅读
nvd116 天前
深入剖析:GCP Pub/Sub 与 Apache Kafka 对消息处理延迟与消费者卡死的处理机制异同
分布式·kafka·apache
笔墨登场说说6 天前
centos 8 使用 kafka_2.13-4.3.1.tgz 安装kafka
linux·kafka·centos
guo_wen_qiang6 天前
kafka一直restarting,报错InconsistentClusterIdException
分布式·kafka
今年下半年6 天前
【消息队列】Spring Boot 集成 Kafka 消息队列:确保消费完成(手动提交偏移量+幂等判断+失败重试机制)
spring boot·kafka·幂等·失败重试
此时不提桶,更待何时7 天前
06-14-A-Kafka集群运维与迁移实战详解
运维·kafka