Skip to content

1. Kafka 生产者怎么保证消息不丢失

发送成功必须有确认,失败要能重试,重试时还不能把消息搞重

第一,确认机制要开强一点。 生产者发送消息后,不能只管发不管结果,通常会把确认级别设高一些,至少要让 Kafka 明确告诉我这条消息到底有没有真正写进去。

第二,要开启重试。 如果网络抖动或者 Broker 短暂异常,发送失败后要能自动重试,而不是直接丢掉。

第三,要考虑重复问题。 因为一旦重试,就可能出现“其实第一次成功了,但我没收到确认,于是又发了一次”。 所以一般还要配合幂等机制,避免重试导致重复消息。

第四,不能只盯生产者自己。 如果业务要求特别高,比如订单、支付,只靠 Kafka 参数还不够,通常还会加本地消息表或者补偿机制。也就是说,先把业务数据和待发送消息一起落库,再异步投递,失败了还能补发。

可以直接背这个版本:

“Kafka 生产者要保证消息不丢,核心就是三点:发送要有确认、失败要能重试、重试要避免重复。”

2.MQ 如何实现延迟消息?Java 里的延迟队列怎么实现?

中间件层面,不同 MQ 实现方式不一样:

  • 有的原生支持延迟消息,直接设置延迟时间就行
  • 有的是通过死信队列加 TTL 实现
  • 也有的是用定时扫描、时间轮这类机制实现

核心思想都一样:不是立刻投递给消费者,而是先存起来,等到指定时间再投递。

它本质上是一个无界阻塞队列,里面放实现了延迟接口的元素。每个元素都有一个到期时间,只有到时间了,消费者才能取出来。 所以它适合做本地定时任务、订单超时取消、延迟重试这种场景。

MQ 延迟消息是“消息先存着,到点再投递”;Java 延迟队列是“任务先入队,到点再消费”。

3.如果 MQ 超过重试次数怎么办?进入死信队列又该如何处理?

一般流程是这样的:

  • 消费失败先重试
  • 超过最大重试次数后,转入死信队列
  • 死信队列里的消息不能一直躺着不管,要有专门处理机制

进入死信队列后的后续处理一般有几种:

  • 人工排查后重新投递
  • 写补偿任务定时扫描死信队列
  • 按失败原因分类处理,比如参数问题直接丢弃,依赖服务异常可以恢复后重试
  • 做告警,避免问题长期没人发现

死信队列不是最终方案,它只是把“处理不了的消息”先隔离出来,真正关键的是后面的补偿、告警和人工兜底。