Kafka消息重试与死信队列(Dead Letter Queue)设计
在实际生产环境中,Kafka消费者处理消息可能失败。请设计一个完整的消息重试架构,包括重试Topic的设计(可延迟重试)、重试次数限制、以及死信队列(DLQ)的存储和告警策略。请用Java伪代码说明Kafka消费端重试的实现。
回答
编译有声
重试与死信架构设计:
-
Topic设计:
orders-topic:主消费Topicorders-retry-1:第1次重试(延迟5s)orders-retry-2:第2次重试(延迟30s)orders-retry-3:第3次重试(延迟10min)orders-dlq:死信队列(最终失败)
-
架构流程:
主Topic → 消费失败 → headers中retryCount=1 → retry-1 retry-1 → 消费失败 → headers中retryCount=2 → retry-2 retry-2 → 消费失败 → headers中retryCount=3 → retry-3 retry-3 → 消费失败 → DLQ -
延迟实现:
- 方式1:Kafka本身不支持延迟,使用定时任务(如延时队列发送到retry Topic)
- 方式2:基于时间戳过滤,消费者只处理时间戳≤当前时间的消息
- 方式3:集成Redis/ZK实现延迟消息
-
死信队列DLQ:
- 单独Topic:
app-dlq - 记录原始消息体 + 失败原因 + 重试次数 + 时间戳
- 告警:钉钉/Slack通知SRE,失败次数超过阈值触发
- 单独Topic:
-
Java伪代码:
void processMessage(ConsumerRecord<String, String> record) {
try {
// 业务处理
process(record.value());
consumer.commitSync();
} catch (Exception e) {
int retryCount = getRetryCount(record.headers());
if (retryCount < MAX_RETRIES) {
// 发送到延迟重试Topic
sendToRetryTopic(record, retryCount + 1);
} else {
// 发送到DLQ
sendToDLQ(record, e.getMessage());
}
}
}