一、基础概念
- 什么是 RabbitMQ?
- 基于 AMQP 协议的开源消息中间件,用于实现系统间的异步通信和解耦,支持多种消息模式(如发布/订阅、路由、主题等)。
- 你了解那个rabbitmq, rabbitmq 的 虚拟机是啥?
****RabbitMQ的虚拟主机(Vhost)主要用于提供逻辑上的隔离,使得在同一RabbitMQ实例上可以运行多个完全隔离的环境。这种隔离性对于资源管理、权限控制和多租户架构等方面至关重要1。
具体作用和好处
- 隔离性:Vhost提供了隔离性,使得一个Vhost内的消息、队列和交换机等资源对于其他Vhost来说是不可见和不可访问的。这对于多用户或多项目场景尤其重要,可以避免不同项目之间的相互干扰1。
- 管理性:每个Vhost可以有独立的权限控制,这使得对不同项目或团队的管理变得简单,简化了管理工作1。
- 安全性:Vhost的隔离和权限控制增强了系统的安全性,即使是在相同的物理服务器上,不同Vhost之间的操作也不会相互影响1。
具体应用场景
多租户架构中,每个租户可以拥有自己的Vhost,从而确保数据和资源的隔离。此外,在大型组织中,不同的团队或项目可以使用不同的Vhost来管理资源和权限,提高整体的系统管理和安全性
-
rabbitmq 支持的模式有哪几种,回答不好,好长时间都不用了,简历上写的有的招聘公司,要求rabbitmq
-
****简单模式****(Simple):一个生产者(P)和一个消费者(C),消息只能被单个消费者处理,适用于消息只能被单个消费者处理的场景12。
-
****工作队列模式****(Work Queue):一个生产者(P)和多个消费者(C1, C2),消息会被分派给不同的消费者,每个消费者接收不同的消息,适用于集群环境中做异步处理12。
-
****发布/订阅模式****(Publish/Subscribe):一个生产者(P)和多个消费者(C1, C2),消息会被复制多份,每个消费者接收相同的消息,适用于消息需要被多个消费者同时接收的场景12。
-
****路由模式****(Routing):生产者将消息发送到交换机,交换机根据路由键将消息路由到特定的队列,适用于有选择地接收消息的场景34。
-
****主题模式****(Topics):类似于路由模式,但可以使用模式匹配来选择性地接收消息,适用于需要根据特定规则接收消息的场景34。
-
RabbitMQ 的核心组件有哪些?
-
Producer:消息生产者。
-
Consumer:消息消费者。
-
Exchange:路由消息到队列(类型:direct、topic、fanout、headers)。
-
Queue:存储消息的容器。
-
Broker:RabbitMQ 服务端,负责消息的接收、存储和转发。
- AMQP 协议的核心概念?
- Connection(连接)、Channel(信道)、Virtual Host(虚拟主机)、Exchange(交换机)、Queue(队列)、Binding(绑定)。
二、Exchange 类型与路由
- Exchange 的四种类型及其区别?
-
Direct Exchange:严格匹配 Routing Key。
-
Topic Exchange:通过通配符(`*`、``)匹配 Routing Key。
-
Fanout Exchange:广播消息到所有绑定的队列。
-
Headers Exchange:根据消息头(Headers)的键值对匹配(较少使用)。
- 如何实现发布/订阅模式?
- 使用 Fanout Exchange,将消息广播到所有绑定的队列。
- 如何实现路由模式?
- 使用 Direct Exchange,通过 Binding Key 和 Routing Key 匹配。
三、消息可靠性
- 如何保证消息不丢失?
- 持久化:设置消息的 `delivery_mode=2`,并声明持久化的 Exchange 和 Queue。
在RabbitMQ中,消息的持久性可以通过deliveryMode
属性来设置。当deliveryMode
设置为2时,表示消息需要被持久化存储。这意味着即使RabbitMQ服务器重启,这些消息也不会丢失。相反,如果deliveryMode
设置为1(默认值),则消息不会被持久化,服务器重启后这些消息将会丢失。
-
确认机制:
-
Publisher Confirms:生产者等待 Broker 的 ACK 确认。
-
Consumer Acknowledgements:消费者手动发送 ACK,失败时 NACK 或拒绝消息。
- 消息重复消费如何解决?
- 消费者端实现幂等性(如数据库唯一索引、Redis 去重)。
四、高可用与集群
- RabbitMQ 集群如何实现高可用?
-
镜像队列(Mirrored Queues):消息在多个节点间同步,主节点故障时从节点接管。
-
集群搭建:通过 Erlang Cookie 同步,节点间共享元数据(队列元数据需显式同步)。
- 集群节点宕机如何处理?
- 若队列为镜像队列,其他节点自动接管;若非镜像队列,队列不可用。
- 网络分区(Network Partition)如何处理?
- 手动干预选择分区策略(如 pause_minority、autoheal),避免脑裂。
五、高级特性
- 什么是死信队列(DLX)?
- 当消息被拒绝、过期或队列达到最大长度时,会被路由到死信队列。常用于订单超时处理。
- 如何实现延迟队列?
- 方案1:利用 TTL + 死信队列(消息设置 TTL,队列设置死信交换机)。
java
String deadLetterExchange = "dlx.exchange";
String deadLetterQueue = "dlx.queue";
String deadRoutingKey = "dlx.routingkey";
String orderExchange = "order.exchange";
String orderQueue = "order.queue";
String orderRoutingKey = "order.routingkey";
args.put("x-dead-letter-exchange", deadLetterExchange); // 绑定死信交换
args.put("x-dead-letter-routing-key", deadRoutingKey); // 设置死信路由键
args.put("x-max-length", 5); // 队列最大容量
args.put("x-message-ttl", 60000); // 队列中消息的全局
channel.queueDeclare(deadLetterQueue,false,false,false,null);
channel.exchangeDeclare(deadLetterExchange, BuiltinExchangeType.DIRECT);
channel.queueBind(deadLetterQueue,deadLetterExchange,deadRoutingKey,null);
channel.queueDeclare(orderQueue,true,false,false,args);
channel.exchangeDeclare(orderExchange, BuiltinExchangeType.DIRECT, true);
channel.queueBind(orderQueue, orderExchange, orderRoutingKey);
AMQP.BasicProperties properties = new AMQP.BasicProperties.Builder()
.expiration("60000") // 设置消息的TTL为60000毫秒(1分钟)
.build();*/
- 方案2:使用 RabbitMQ 插件(如 `rabbitmq-delayed-message-exchange`)。
java
Map<String, Object> args = new HashMap<>();
args.put("x-delayed-type", "direct");
channel = connection.createChannel();
channel.exchangeDeclare("delayed.exchange", "x-delayed-message", true, false, args);
channel.queueDeclare("delayed.queue",true,false,false,null);
channel.queueBind("delayed.queue","delayed.exchange","order.delay",null);
Map<String,Object> header = new HashMap<>();
header.put("x-delay", 5000); // 延迟5秒
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.headers(header)
.deliveryMode(2)
.expiration("10000")
.build();
- 优先级队列如何实现?
- 声明队列时设置 `x-max-priority` 参数,消息设置 `priority` 属性。
六、问题排查与优化
- 如何监控 RabbitMQ?
-
使用管理插件(`rabbitmq-management`)查看队列状态、消息数量、节点状态等。
-
监控工具:Prometheus + Grafana 监控内存、磁盘、消息积压等指标。
- 消息堆积如何处理?
-
横向扩容消费者,增加并发消费能力。
-
设置 QoS(预取计数),避免单个消费者过载。
- 内存和磁盘使用过高怎么办?
-
调整内存阈值(`vm_memory_high_watermark`)。
-
优化消息持久化策略,非必要消息不持久化。
七、应用场景与设计
- RabbitMQ 的典型应用场景?
- 异步处理(如订单生成后发短信)、系统解耦、流量削峰(如秒杀)、事件驱动架构。
- 如何用 RabbitMQ 实现分布式事务?
-
本地消息表:业务操作与消息记录在同一个本地事务,定时任务补偿未确认的消息。
-
最大努力通知:多次重试确保消息最终被处理。
- 如何保证消息顺序性?
- 单队列 + 单消费者,或使用分区有序(如 Kafka 分区键)。
八、对比与选型
- RabbitMQ vs Kafka?
-
RabbitMQ:适合复杂路由、低吞吐、高可靠场景(如金融交易)。
-
Kafka:适合高吞吐、日志流处理、大数据场景(如日志收集)。
- RabbitMQ 与其他 MQ(如 RocketMQ)对比?
- RocketMQ 支持事务消息、顺序消息更强,适合超大规模分布式系统。
九、开放性问题
- 如何保证消息不重复且不丢失?
-
生产者:Confirm 机制 + 重试。
-
消费者:手动 ACK + 幂等性设计。
-
存储层:消息持久化 + 死信队列兜底。
- 如何传输大文件?
- 不建议直接通过消息传输,可上传至文件服务器,消息中传递下载链接。