1. 什么是 RabbitMQ?
答 :
RabbitMQ 是一个开源的、基于 Erlang 语言 开发的消息中间件,实现了 AMQP(Advanced Message Queuing Protocol) 协议。它支持消息的异步通信、解耦、削峰、可靠投递等功能,广泛应用于分布式系统中。
2. RabbitMQ 的使用场景有哪些?
答:
- 系统间异步通信(如用户注册后发邮件)
- 流量削峰(秒杀、抢购)
- 应用解耦(订单系统与库存、物流解耦)
- 顺序消费(需保证消息处理顺序)
- 定时任务/延迟任务(结合插件或 TTL+死信队列)
3. RabbitMQ 的核心组件有哪些?
答:
- Producer:消息生产者
- Consumer:消息消费者
- Broker:RabbitMQ 服务实例
- Exchange:交换机,决定消息路由规则
- Queue:消息队列,存储消息
- Binding:绑定关系(Exchange ↔ Queue)
- Routing Key:路由键
- VHost:虚拟主机,实现权限隔离
- Channel:轻量级连接通道
4. RabbitMQ 有哪几种工作模式?
答:共 5 种:
- Simple 模式:一对一收发
- Work 模式:多个消费者竞争消费(轮询)
- Publish/Subscribe:广播模式,所有订阅者都收到
- Routing 模式:按 Routing Key 精确匹配队列
- Topic 模式 :模糊匹配(支持
*和#通配符)
5. 如何保证 RabbitMQ 消息不丢失?
答:从三方面保障:
- 生产者 :开启 Confirm 模式,收到 ACK 才认为发送成功
- MQ 服务端 :
- 队列设置
durable=true - 消息设置
deliveryMode=2(持久化)
- 队列设置
- 消费者 :关闭自动 ACK,手动确认(处理成功后再 ack)
⚠️ 三者缺一不可。
6. 如何避免消息被重复消费?
答 :实现消费幂等性:
- 给每条消息分配全局唯一 ID
- 消费前检查该 ID 是否已处理(通过数据库唯一索引 或 Redis 去重表)
- 若已存在,则直接丢弃,不再处理
7. 如何保证消息的顺序性?
答:
- 方案一:单队列 + 单消费者(牺牲并发)
- 方案二:按业务 key(如订单 ID)哈希到同一队列,每个队列对应一个消费者
- 方案三:单消费者内部用内存队列排队,再分发给多个 worker 处理
注意:RabbitMQ 本身不保证跨队列顺序。
8. RabbitMQ 如何实现延迟队列?
答:官方不直接支持,常用方案:
- TTL + 死信队列(DLX) :
- 消息设置 TTL(过期时间)
- 队列绑定死信交换机
- 消息过期后自动进入死信队列,由消费者处理
- 或使用 rabbitmq-delayed-message-exchange 插件
9. RabbitMQ 的消息是如何路由的?
答:流程如下:
- Producer 发送消息到 Exchange,并指定 Routing Key
- Exchange 根据类型和 Binding 规则将消息路由到一个或多个 Queue
- Direct:精确匹配 Routing Key
- Fanout:广播到所有绑定队列
- Topic :支持通配符匹配(
*匹配一个词,#匹配多个)
10. RabbitMQ 使用什么传输协议?
答 :
底层基于 TCP 连接 ,但为提升性能,使用 Channel(信道) 在一条 TCP 上复用多个虚拟连接,减少连接开销。
11. 什么是 VHost?作用是什么?
答 :
VHost(Virtual Host)是 RabbitMQ 中的虚拟 Broker ,相当于一个独立的 MQ 实例,包含自己的 Exchange、Queue、Binding 和权限体系。
作用:实现多租户隔离,例如不同项目/环境使用不同 VHost,互不影响。
12. RabbitMQ 如何实现高可用?
答 :通过 镜像队列(Mirrored Queue):
- 创建策略(Policy),指定队列为镜像模式
- 队列数据自动同步到多个节点
- 主节点宕机后,从节点自动接管,消费者无感知
普通集群仅同步元数据,不防消息丢失。
13. 消息积压几百万条怎么办?
答:紧急处理步骤:
- 修复消费者,恢复消费能力
- 临时扩容 :
- 新建 10 倍数量的队列
- 写临时程序快速消费积压消息并分发到新队列
- 部署更多消费者并行处理
- 高峰期后补数据(若因 TTL 丢失)
14. 为什么不能对所有消息都持久化?
答:
- 性能下降:磁盘写入比内存慢 10 倍以上
- 集群风险:在镜像集群中,若队列未持久化但消息持久化,节点宕机可能导致消息"黑洞"(blackholed)
- 建议 :仅对关键业务消息做持久化
15. Confirm 模式和 Transaction 模式的区别?
答:
| 对比项 | Confirm 模式 | Transaction 模式 |
|---|---|---|
| 性能 | 高(异步) | 低(同步阻塞) |
| 可靠性 | 高 | 高 |
| 使用频率 | ✅ 推荐 | ❌ 已淘汰 |
Confirm 模式是主流方案。
16. 消费者接收消息后没处理就宕机了,消息会丢失吗?
答 :不会丢失,前提是:
- 使用了 手动 ACK
- 消费者断开连接前未发送 ACK
此时 RabbitMQ 会将消息重新入队,分发给其他消费者。
17. RabbitMQ 支持事务吗?
答 :支持,通过 channel.txSelect() 开启事务,但性能极差 ,不推荐生产使用。应优先使用 Confirm 模式。
18. 如何监控 RabbitMQ?
答:
- 使用 Management Plugin(Web 控制台)
- 查看队列长度、消费者数量、消息速率、内存/CPU 使用
- 集成 Prometheus + Grafana 做指标监控
- 设置告警(如队列堆积超过阈值)
19. RabbitMQ 中的死信队列(DLQ)是什么?
答 :
当消息满足以下条件之一时,会变成"死信",进入死信队列:
- 被拒绝(basic.reject / basic.nack)且 requeue=false
- TTL 过期
- 队列达到最大长度
用途:处理异常消息、实现延迟队列、错误重试等。
20. RabbitMQ 最多支持多少连接和队列?
答 :
受限于系统资源(内存、文件描述符):
- 默认单节点可支持 数万个连接
- 队列数量可达 数十万级
- 实际需根据硬件和配置调优(如 Erlang VM 参数)
21. RabbitMQ 和 Kafka 的主要区别?
答:
| 维度 | RabbitMQ | Kafka |
|---|---|---|
| 设计目标 | 通用消息队列 | 高吞吐日志流 |
| 吞吐量 | 中等(万级/秒) | 极高(百万级/秒) |
| 延迟 | 低(毫秒级) | 中(几十毫秒) |
| 消息模型 | Queue / PubSub | Topic Partition |
| 持久化 | 支持 | 强依赖磁盘顺序写 |
| 适用场景 | 业务解耦、异步任务 | 日志采集、实时计算 |
22. 如何测试 RabbitMQ 的可靠性?
答:可通过以下方式验证:
- 模拟网络分区(使用 Chaos Engineering 工具)
- 强制 kill 节点,观察镜像队列是否切换
- 关闭消费者,查看消息是否堆积
- 发送大量消息,验证是否丢失(配合唯一 ID 校验)
- 开启持久化后重启 MQ,检查数据是否恢复