Skip to content
基础

一句话答案

消费失败重试超上限后进入死信队列(DLQ),人工介入处理:修复后重新投递或补偿处理。

核心要点

消费失败的处理策略:

1. 重试机制

第一次失败 → 等待 5s 重试
第二次失败 → 等待 30s 重试
第三次失败 → 等待 1min 重试
...
达到最大重试次数 → 投递到死信队列

(指数退避策略,避免频繁重试打爆下游)

2. 死信队列(Dead Letter Queue,DLQ)

死信队列是专门存放"处理失败"消息的队列,消息进入死信队列的条件:

① 消息消费失败且超过最大重试次数
② 消息在队列中等待超过 TTL(消息过期)
③ 队列长度超过上限(消息被挤出)

RocketMQ 的死信队列:

java
// 消费失败达到最大重试次数(默认16次)后,自动投入死信队列
// 死信 Topic 名称:%DLQ%消费者GroupID

// 监控和处理死信:
consumer.subscribe("%DLQ%MyConsumerGroup", "*");
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
    // 告警、人工处理、记录到 DB 等
    alertService.sendAlert(msgs.get(0));
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});

Kafka 的死信队列(需自己实现):

java
// Kafka 没有原生死信队列,需要自己实现:
public void consume(ConsumerRecord<String, String> record) {
    int retryCount = getRetryCount(record);
    
    try {
        process(record);
    } catch (Exception e) {
        if (retryCount < MAX_RETRY) {
            // 发到重试 Topic(延迟一定时间)
            producer.send(new ProducerRecord<>("topic-retry-" + retryCount, record.value()));
        } else {
            // 达到最大重试,发到死信 Topic
            producer.send(new ProducerRecord<>("topic-dead-letter", record.value()));
            // 告警
        }
    }
}

处理死信的策略:

  1. 人工介入:告警 → 运营人员在控制台查看死信 → 手动重新处理
  2. 自动重试:定时任务将死信重新投递(配合幂等性)
  3. 降级处理:记录到数据库,由补偿任务处理
追问与易错

追问方向:

  • 这个概念在你的项目中是怎么应用的?
  • 和相关技术/方案相比有什么优劣?
  • 如果出了问题你会怎么排查?

易错点:

  • ❌ 只知道概念不知道原理——面试官会追问底层实现
  • ❌ 缺乏实际使用经验——结合项目场景回答更有说服力

💡 记忆锚点

死信队列 = 退件仓库:快递反复投递失败(重试超上限)就送到退件仓,等人工处理。三种进仓条件:投递次数用光、放太久过期、队列满了被挤出。RocketMQ自带退件仓(%DLQ%),Kafka得自己建。