可以参考之前的rabbitmq的全部内容博客rabbitmq
1. 介绍一下 RabbitMQ 的核心组件和工作原理
💡 知识点解析:
想象成寄快递:
-
Producer(生产者): 寄件人。
-
Exchange(交换机): 快递分拣中心。它不存快递,只负责按地址(Routing Key)分发。
-
Queue(队列): 具体的快递站点/仓库。快递存在这里。
-
Binding(绑定): 分拣中心到站点的卡车路线。
-
Consumer(消费者): 收件人。
🗣️ 面试参考回答:
"RabbitMQ 的工作模型是基于 AMQP 协议的。它的核心组件主要包括:
-
Producer(生产者): 发送消息的应用。
-
Consumer(消费者): 接收和处理消息的应用。
-
Exchange(交换机): 接收生产者发送的消息,并根据路由键 (Routing Key)将消息路由到绑定的队列 中。它本身不存储消息。
-
Queue(队列): 存储消息的容器,消息在这里等待被消费。
工作原理是:
生产者将消息发送给交换机,交换机根据Routing Key(路由键)和Binding(绑定关系),将消息转发到具体的Queue(队列)。消费者监听队列,从队列中获取消息进行消费。"
2. 交换机 (Exchange) 有哪些类型?
💡 知识点解析:
分拣中心的策略:
-
Fanout: 广播。不管地址,所有连我的站点都给一份。
-
Direct: 直连。地址必须完全匹配。
-
Topic: 主题。地址可以模糊匹配(比如
*.news)。 -
Headers: 看信封属性(不常用)。
🗣️ 面试参考回答:
"RabbitMQ 常用的交换机类型有四种:
-
Direct Exchange(直连交换机): 路由键完全匹配 。消息的 Routing Key 必须和 Binding Key 完全一致才会被转发,常用于点对点通信。
-
Fanout Exchange(广播交换机): 忽略路由键,将消息广播到所有绑定到该交换机的队列。速度最快。
-
Topic Exchange(主题交换机): 支持通配符 匹配。Routing Key 可以包含
*(匹配一个 单词)和#(匹配零个 或多个单词),非常灵活。 -
Headers Exchange: 根据消息头的属性进行匹配,而不是路由键。在实际开发中用得比较少。"
3. RabbitMQ 中有哪些消息模型?
💡 知识点解析:
通常指 RabbitMQ 官方教程提到的 5 种模式:
-
简单队列(一对一)。
-
工作队列(多个人干活,轮流分发)。
-
发布订阅(广播,Fanout)。
-
路由模式(Direct)。
-
主题模式(Topic)。
🗣️ 面试参考回答:
"RabbitMQ 提供了多种消息模型,最常用的包括:
-
基本消息模型 (Hello World): 一个生产者对应一个队列 和一个消费者。
-
工作队列模型 (Work Queues): 一个队列绑定多个消费者 ,消息在消费者之间轮询分发(或者通过能者多劳模式公平分发),用于处理耗时任务。
-
发布/订阅模型 (Publish/Subscribe): 使用 Fanout**(广播)** 交换机,将消息广播给所有绑定的队列。
-
路由模型 (Routing): 使用 Direct(直接 ) 交换机,根据路由键有选择地将消息发给特定队列。
-
主题模型 (Topics): 使用 Topic (主题 )交换机,通过通配符进行更灵活的路由。"
4. RabbitMQ 如何确保消息的可靠性?
💡 知识点解析:
消息不能丢,得全链路保障:
-
发的时候: 生产者要确认 MQ 收到了(Confirm/Return 机制)。
-
存的时候: MQ 自己挂了怎么办?(持久化)。
-
收的时候: 消费者处理失败了怎么办?(手动 Ack)。
🗣️ 面试参考回答:
"消息可靠性需要从发送端、MQ 服务端、消费端三个维度来保证:
-
发送端可靠性: 开启 ConfirmCallback (发布确认)和 ReturnCallback(回退模式)。确保消息成功到达交换机,且被路由到了队列。如果失败,可以进行重试或记录日志。
-
服务端可靠性: 开启持久化。包括 Exchange 持久化、Queue 持久化和 Message 持久化(deliveryMode=2),防止 MQ 重启导致数据丢失。
-
消费端可靠性: 使用 手动 ACK 机制(basicAck)。只有当业务逻辑执行成功后,才告诉 MQ 删除消息。如果执行失败,可以拒绝消息(basicNack)并让其重新入队,或者进入死信队列。"
5. RabbitMQ 如何保证消息的幂等性?
💡 知识点解析:
和微服务篇的接口幂等性一样。MQ 重复消费是必然会发生的(比如网络抖动导致 Ack 丢失),所以消费者必须能处理重复消息。
核心:判重。
🗣️ 面试参考回答:
"MQ 的重复消费是不可避免的(例如网络波动导致 ACK 丢失),所以必须在消费者端保证幂等性。常见的方案有:
-
利用 Redis 原子性: 每条消息在生产时生成一个全局唯一的 ID(MessageID)。消费前先去 Redis 查一下这个 ID 是否存在。如果存在,说明消费过了;如果不存在,则执行业务并把 ID 存入 Redis。
-
数据库唯一索引: 如果业务是写数据库,可以利用数据库的主键或唯一约束。重复插入会抛出异常,捕获异常忽略即可。
-
乐观锁: 如果是更新操作,可以带上版本号条件。"
6. 什么是死信队列?消息是如何成为死信的?
💡 知识点解析:
死信 = "没人要"或"处理不了"的消息。
MQ 只有死信交换机 (DLX),没有专门的死信队列。绑定到 DLX 的队列就叫死信队列。
来源:
-
被拒收了(reject)且不让重发(requeue=false)。
-
过期了(TTL)。
-
队列满了(Max length)。
🗣️ 面试参考回答:
"死信队列是指用来存放那些无法被正常消费的消息的队列。
消息成为'死信'(Dead Letter)通常有三种情况:
-
消息被拒绝: 消费者使用
basic.reject或basic.nack拒绝消息,并且设置requeue=false(不再重新入队)。 -
消息过期: 消息设置了 TTL(Time To Live),在规定时间内没有被消费。
-
队列达到最大长度: 队列的消息数量超过了最大限制,最早的消息会被挤掉成为死信。
通常我们会给队列绑定一个死信交换机(DLX),当消息变成死信时,会自动转发到这个交换机,进而进入死信队列,用于后续的人工排查或重试。"
7. 什么是延迟队列?RabbitMQ 如何实现延迟队列?
💡 知识点解析:
场景: 下单 30 分钟不支付自动取消。
RabbitMQ 原生不支持延迟队列(不像 Java DelayQueue)。
野路子实现: 消息设置过期时间 (TTL) + 死信队列 (DLQ)。消息死了以后才会被消费者看到。
正规路子: 安装插件 rabbitmq_delayed_message_exchange。
🗣️ 面试参考回答:
"延迟队列是指消息发送后,消费者不会立刻收到,而是等待指定时间后才能消费。常用于'订单超时取消'等场景。
RabbitMQ 实现延迟队列主要有两种方案:
-
TTL + 死信队列(最常用): 创建一个没有消费者的 TTL 队列 (设置过期时间),并绑定死信交换机 。消息发进去后,过期变成死信,被转发到死信队列,消费者监听死信队列,从而实现延迟效果。
-
使用延迟插件: 安装
rabbitmq_delayed_message_exchange插件 。它允许交换机暂存消息,等到时间到了再投递给队列。这种方式更简单,不需要创建死信队列。"
8. 如何解决 RabbitMQ 的消息堆积问题?
💡 知识点解析:
池子里的水快溢出来了。
原因: 生产太快,消费太慢(或者消费者挂了)。
解决:
-
赶紧修: 修复消费者 Bug。
-
加人手: 多开几个消费者进程。
-
临时扩容(大招): 原消费者只负责转发,转发到新的临时 Topic,那边开 10 倍的消费者慢慢处理。
🗣️ 面试参考回答:
"消息堆积通常是因为消费者处理速度跟不上生产者发送速度。解决方案如下:
-
增加消费者数量: 在服务器允许的范围内,增加 Consumer 实例 或线程数,提高并发消费能力。
-
优化消费逻辑: 检查消费者代码,是否有耗时操作(如慢 SQL、第三方接口),尽量异步处理或优化性能。
-
临时扩容(紧急方案): 如果堆积非常严重,原来的消费者处理不过来,可以修改消费者程序,将消息快速转发到一个新的、拥有几十个分区的临时 Topic/Queue 中,然后临时启动几十个消费者去专门处理这些积压消息。"
9. RabbitMQ 的集群方案有哪些?
💡 知识点解析:
-
普通集群: 大家只同步"目录"(元数据 ),不同步"文件"(消息)。A 节点挂了,B 节点只有目录,没法给用户数据。
-
镜像集群(Mirror Queue): 真正的 HA(高可用)。数据在节点间同步复制。A 挂了 B 能顶上。
🗣️ 面试参考回答:
"RabbitMQ 常用的集群模式主要有两种:
-
普通集群模式: 默认模式。所有节点同步交换机、队列的元数据 (结构),但消息实体只存储 在创建队列 的那个节点 上。如果该节点宕机,消息将不可用。它主要用于提高吞吐量,不能保证高可用。(仅同步元数据,不备份消息,用于提高吞吐量,无高可用。)
-
镜像队列模式(Mirror Queue): 这是实现**高可用 (HA)**的方案。配置策略 将队列的消息在多个节点 之间进行同步复制 (主从结构)。如果 Master 节点挂了,会自动选举一个 Slave 接管。生产环境一般都使用这种模式。"目前在最新版中已被标记为废弃。
-
仲裁队列(新版 HA): 这是目前生产环境的首选,用于替代镜像队列的 。它是基于 Raft 一致性算法 实现的。与镜像队列不同,它不需要所有节点都同步数据,只要超过半数(Quorum) 的节点写入成功即可。它在保证数据安全的同时,大幅解决了旧版镜像队列在网络波动时的性能问题。"
-

10. RabbitMQ 和 Kafka 的区别?
💡 知识点解析:
-
RabbitMQ: 精致的跑车。快,功能多(路由、重试、顺序),可靠性高,但装得少(吞吐量一般,堆积千万级性能下降)。
-
Kafka: 大货车。装得多(吞吐量极高,百万级),不仅能跑还能存(日志存储),但功能相对粗糙(以前没有事务、延迟队列等)。
🗣️ 面试参考回答:
"它们侧重点不同,选型依据如下:
-
吞吐量: Kafka 设计初衷是处理日志 ,吞吐量极高 (百万级/秒);RabbitMQ 吞吐量较低(万级/秒)。
-
可靠性与功能: RabbitMQ 支持复杂的路由逻辑、死信、延迟队列 等,消息可靠性更好 ,适合业务逻辑复杂、一致性要求高 的场景(如订单、支付)。Kafka 适合大数据量、流式计算、日志采集等场景。
-
架构模式: RabbitMQ 是基于推 (Push)模式(也有拉 );Kafka 是基于拉(Pull)模式,只管存,消费者记录消费进度(Offset)。"