外观
一句话答案
消费失败重试超上限后进入死信队列(DLQ),人工介入处理:修复后重新投递或补偿处理。
核心要点
消费失败的处理策略:
1. 重试机制
第一次失败 → 等待 5s 重试
第二次失败 → 等待 30s 重试
第三次失败 → 等待 1min 重试
...
达到最大重试次数 → 投递到死信队列
(指数退避策略,避免频繁重试打爆下游)1
2
3
4
5
6
7
2
3
4
5
6
7
2. 死信队列(Dead Letter Queue,DLQ)
死信队列是专门存放"处理失败"消息的队列,消息进入死信队列的条件:
① 消息消费失败且超过最大重试次数
② 消息在队列中等待超过 TTL(消息过期)
③ 队列长度超过上限(消息被挤出)1
2
3
2
3
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;
});1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
处理死信的策略:
- 人工介入:告警 → 运营人员在控制台查看死信 → 手动重新处理
- 自动重试:定时任务将死信重新投递(配合幂等性)
- 降级处理:记录到数据库,由补偿任务处理
追问与易错
追问方向:
- 这个概念在你的项目中是怎么应用的?
- 和相关技术/方案相比有什么优劣?
- 如果出了问题你会怎么排查?
易错点:
- ❌ 只知道概念不知道原理——面试官会追问底层实现
- ❌ 缺乏实际使用经验——结合项目场景回答更有说服力
💡 记忆锚点
死信队列 = 退件仓库:快递反复投递失败(重试超上限)就送到退件仓,等人工处理。三种进仓条件:投递次数用光、放太久过期、队列满了被挤出。RocketMQ自带退件仓(%DLQ%),Kafka得自己建。