☰
Java高级后端 · 全套面试通关手册(RabbitMQ)
2026/10/1 19:52:40 网站建设 项目流程

核心思路:生产者 -> 交换机 Exchange -> 队列 Queue -> 消费者;AMQP 协议。

1.基础概念

  1. Broker:RabbitMQ 服务实例,一个 Broker 包含多个 VirtualHost。

  2. VirtualHost(vhost):虚拟主机,隔离资源(交换机、队列),可以分配权限,类似数据库的库。

  3. Exchange 交换机:接收生产者消息,根据路由规则转发到队列。

  4. Queue 队列:存储消息,等待消费者消费。

  5. Binding 绑定:交换机和队列之间的绑定关系,绑定需要 routingKey。

  6. RoutingKey 路由键:生产者发送消息携带,用来匹配绑定规则。

  7. BindingKey 绑定键:绑定时指定,交换机根据 routingKey 匹配 bindingKey。

4 种交换机类型⭐高频

  1. Direct(直连):routingKey 完全匹配 bindingKey,消息发送到对应队列。点对点场景。

  2. Fanout(广播):忽略 routingKey,消息分发到所有绑定该交换机的队列。群发、通知场景。

  3. Topic(主题):模糊匹配。*匹配一个单词;#匹配 0 或多个单词。日志分类最常用。

  4. Headers:不使用 routingKey,通过消息 header 属性匹配,性能差,很少使用。

2.消息可靠(三大可靠性:生产者、Broker、消费者)

(1)生产者消息投递确认(保证消息成功到达 Broker)

  • Confirm 确认机制:生产者开启 publisher-confirm-type。消息到达 Broker 返回 ack;失败返回 nack。异步回调。

  • Return 退回机制:消息到达交换机,但是找不到匹配队列,消息退回生产者。

Confirm 保证消息成功抵达 exchange;Return 保证消息成功路由到 queue。

(2)Broker 持久化(宕机不丢消息)

  • 交换机持久化:durable=true

  • 队列持久化:durable=true

  • 消息持久化:deliveryMode=2

三者都配置,消息写入磁盘。但刷盘是操作系统异步,极端断电仍可能丢失。

(3)消费者消息确认 ACK(防止消息丢失、重复消费)

  • 自动 ACK(默认):消息分发成功就自动 ack。消费者还没处理完宕机 → 消息丢失,生产禁用。

  • 手动 ACK:业务处理成功,调用basicAck;处理失败:

    • basicNack:拒绝,可以 requeue=true 重回队列;requeue=false 丢弃 / 转入死信。

    • basicReject:一次拒绝单条消息。

生产推荐手动 ACK。

3.死信队列 DLX(重点)

死信:消息无法被正常消费,变成死信。 触发死信条件:

  1. 消息被 nack,requeue=false

  2. 消息 TTL 过期

  3. 队列消息数量达到最大长度

DLX 原理:给普通队列绑定死信交换机;消息变成死信,自动转发到死信交换机,路由到死信队列。

适用场景:延时队列、失败消息归档重试。

RabbitMQ 没有原生延时队列,TTL+DLX 模拟延时队列;缺陷:队列过期,是在消息出队时检测,不是消息到期立刻转发。

4.消息重复消费(幂等)

MQ 无法避免重复投递(网络抖动,ack 丢失,Broker 重复推送)。

解决方案:业务端实现幂等

  1. 唯一消息 ID,数据库唯一索引

  2. Redis 记录已消费消息 id

  3. 状态机,根据业务状态判断是否处理

口诀:MQ 不保证只投递一次,只能保证至少投递一次 at-least-once

5.消息堆积问题⭐面试高频

原因

消费者消费速度远低于生产速度;消费者宕机;消费逻辑阻塞。

解决方案

  1. 排查消费代码,优化消费逻辑,去掉慢 IO

  2. 增加消费者数量,提高消费能力(同一队列,多消费者轮询消费)

  3. 批量消费

  4. 堆积严重:临时扩容队列,分流;紧急场景可以丢弃无效消息

注意:不要盲目提高 prefetch。prefetch 是预取数量。

Prefetch(预取)

basicQos (prefetchCount),告诉 MQ 一次性预取 N 条消息给消费者,未 ack 前不再推送。 作用:流量控制,防止消费者一次性被压爆。

6.消息丢失全链路总结

生产者丢消息 → 开启 Confirm+Return Broker 丢消息 → 交换机、队列、消息持久化 消费者丢消息 → 关闭自动 ACK,使用手动 ACK

7.其他高频知识点

(1)集群模式

  1. 普通集群:消息只存在单个节点,其他节点仅元数据;访问其他节点会转发。

  2. 镜像队列(RabbitMQ3.8 后弃用):消息同步到多个节点,高可用。

  3. 仲裁队列 Quorum Queue(3.8 + 推荐):Raft 协议,数据多副本,替代镜像队列,高可用。

(2)消费模式

  • 轮询:默认,消息均匀分给多个消费者

  • 公平分发:配合 prefetch,谁处理完,给谁下一条

(3)事务

RabbitMQ 支持生产者事务(channel.txSelect),性能极差,生产几乎不用;优先 Confirm。

高频深挖面试题

Q1:AMQP 和 Kafka 的协议区别?

RabbitMQ AMQP 是应用层协议;Kafka 自定义二进制协议。AMQP 面向消息投递可靠性,Kafka 面向高吞吐。

Q2:为什么不推荐用事务,改用 Confirm?

事务同步阻塞,性能差;Confirm 异步回调,吞吐量更高。

Q3:死信队列 TTL 两种设置方式?

消息级别 TTL(每条消息单独过期时间);队列级别 TTL(队列内所有消息统一过期)。队列 TTL 更推荐。

Q4:什么是 At most once / At least once / Exactly once?

At most once:最多一次,可能丢消息(自动 ack) At least once:至少一次,可能重复(手动 ack,生产常用) Exactly once:恰好一次,MQ 做不到,业务幂等实现。

Q5:仲裁队列和镜像队列区别?

镜像队列全节点同步,性能差,3.8 废弃;仲裁队列基于 Raft,少数副本不可用仍可读,性能更好。

一句话背诵总结

RabbitMQ 基于 AMQP;4 种交换机 Direct/Fanout/Topic/Headers;

消息可靠性分生产者 Confirm、Broker 持久化、消费者手动 ACK;

死信队列 DLX 处理过期 / 拒绝消息;

MQ 只能保证至少投递一次,业务实现幂等解决重复消费;

消息堆积优化消费能力,Quorum 仲裁队列作为高可用方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询