消息队列高可用
MQ 本身挂了,削峰和解耦全失效。面试主线:集群怎么冗余、消息怎么不丢、消费失败怎么办。
Kafka 集群与副本
Kafka: leader 写, ISR 同步, 故障选举
- 分区多副本:每个分区有 leader(读写)和 follower(同步),副本数 3 是生产标配
- ISR(In-Sync Replicas):与 leader 保持同步的副本集合。写入要求
acks=all时,ISR 全部确认才返回 - 故障转移:leader 挂了从 ISR 选新 leader(比落后太多的副本优先排除,防丢消息)
- 可靠性参数:
acks=all+min.insync.replicas=2(至少 2 个副本确认,防单副本确认后 leader 挂)
RabbitMQ 高可用
| 方案 | 机制 | 说明 |
|---|---|---|
| 镜像队列(经典) | 队列在多个节点镜像 | 主从复制,故障切换 |
| 仲裁队列(现代) | Raft 复制(3-5 副本) | 官方推荐,数据不丢 |
| 集群 | 节点间共享元数据 | 高可用基础 |
要点:RabbitMQ 普通队列只在一个节点(数据单点),镜像/仲裁队列才是高可用形态。publisher confirm + 手动 ack 是消息不丢的标配。
消费重试与死信
重试耗尽进死信
| 机制 | 作用 |
|---|---|
| 重试队列 | 消费失败的消息延迟重投,指数退避(见重试与幂等篇) |
| 死信队列(DLQ) | 重试耗尽的消息进 DLQ,隔离问题消息,不阻塞主队列 |
| 死信处理 | 监控 DLQ 积压、人工修复、补偿任务 |
| 消费幂等 | 重投必然重复,消费端唯一键去重(见重试与幂等篇) |
设计要点:重试要有上限(无限重试 = 队列阻塞);DLQ 要有监控告警(积压说明有系统性 bug);DLQ 里的消息要能重放和人工处理。
消息不丢的完整链路
- 生产:
acks=all(Kafka)/ publisher confirm(RabbitMQ) - 存储:多副本(Kafka ISR / RabbitMQ 仲裁队列)
- 消费:手动 ack(处理成功再确认)
- 失败:重试 + 死信 + 幂等
任何一段偷懒都会丢消息。面试答完整链路是加分项。
面试追问
- Kafka 怎么保证不丢? acks=all + ISR 同步 + min.insync.replicas=2。leader 挂了从 ISR 选举
- ISR 是什么? 与 leader 保持同步的副本集合。写确认和 leader 选举都以 ISR 为准
- 死信队列干什么? 重试耗尽的消息隔离存放,不阻塞主队列。监控积压、人工处理
- RabbitMQ 和 Kafka 的高可用差别? RabbitMQ 仲裁队列 Raft 复制;Kafka 分区副本 ISR 机制。思路一致:多副本 + 确认
- 消费重复怎么办? MQ 至少一次语义,消费端幂等(唯一键)。重试、故障转移都会产生重复