目录
关于其他消息队列的文章: 带你轻松学习Kafka-CSDN博客https://blog.csdn.net/2401_88959292/article/details/149309549?sharetype=blogdetail&sharerId=149309549&sharerefer=PC&sharesource=2401_88959292&spm=1011.2480.3001.8118 带你轻松学习RocketMQ-CSDN博客https://blog.csdn.net/2401_88959292/article/details/149296505?sharetype=blogdetail&sharerId=149296505&sharerefer=PC&sharesource=2401_88959292&spm=1011.2480.3001.8118
一、核心组件/概念
(一)交换机(Exchange)
交换器主要起到一个消息路由作用,根据当前消息的绑定键,将消息路由到对应的队列中。路由规则主要取决于型以及绑定队列的绑定键。
(二)队列(Queue)
队列主要是消息实体存储的缓冲区,其顺序与数据结构一致都是先进先出。
(三)绑定键(binding)
这是消息路由的关键所在,每条消息都拥有自己的绑定键,队列在绑定交换机时也需要声明对应的绑定键,这样才能实现对应的消息发送到对应的队列中去。
二、消息流程


流程说明:
1.生产者发送消息
连接Broker,通道,然后发送消息。
消息在发送之前需要指定以下三个属性:
- 交换机名称
- 绑定键
- 消息实体
2.交换机路由消息
交换机根据当前交换机类型以及接收到的消息所绑定的键来路由消息。
| 交换机类型 | 路由逻辑 |
|---|---|
| Direct | 精确匹配:消息与队列的绑定键完全一致时转发。 |
| Fanout | 广播:忽略绑定键,将消息转发到所有绑定的队列。 |
| Topic | 模糊匹配:将绑定键用通配符(* 匹配单级、# 匹配多级)匹配。 |
| Headers | 基于消息属性(Headers)匹配,不经常使用。 |
3.队列存储消息
当消息被路由到队列后,队列会根据存储进行数据的存储。
存储策略如下:
- 持久化队列:队列元数据存储在磁盘,消息若标记为持久化,则会写入内存和磁盘。
- 非持久化队列:队列和消息仅存于内存。
前者会保障消息数据的零丢失,但是会丢失一部分性能;后者相反。
同时队列还支持长度限制、过期时间等属性,用于流量控制。
4.消费者订阅/消息
消费者同生产者一样,也需要连接Broker并开启通道,同时还需要声明队列和交换机。
提供了以下两种消费方式:
- 推模式(Push):使用
basicConsume订阅队列,主动将消息推送给消费者。 - 拉模式(Pull):使用
basicGet主动从队列拉取消息。
默认为push模式,因为性能更高,承受并发能力更强。
原因是pull模式实际上是轮询每个队列主动拉取消息,这样很可能会造成空轮询,浪费过多网络请求。
5.消费者发送ACK确认
这是RabbitMQ的消息确认机制,是保证消息不丢失的关键:
- 自动 ACK:消费者接收到消息后自动发送ACK,RabbitMQ 立即删除该消息。
- 手动 ACK:消费者处理完成后,需显式发送ACK确认。
前后者的区别在于同步和异步,前者是以消费者宕机会丢失消息的风险换取性能,而后者是通过阻塞队列换取的消息零丢失的强保障。
6.队列删除消息
若队列接收到消费者发来的ACK确认,会直接删除消息实体,即使是持久化消息也会删除其在磁盘中的数据。
若未收到ACK确认,则会重新投递消息,确保消息零丢失。
三、优劣分析
(一)优点
1.消息的零丢失的强保障
RabbitMQ通过三重持久化、生产者确认、消费者确认、高可用集群四大机制,确保消息从生产者到消费者的全链路可靠。
- 持久化:交换机和队列、以及被标记为持久化的消息数据会存储到磁盘。
- 生产者确认:开启
confirm模式后,当消息到达交换机后Broker会发送ack消息给生产者,生产者可根据确认结果重发消息。 - 消费者确认:消费者可选择自动和手动向Broker发送ack消息的方式,从而确保消息是否被消费掉。
- 高可用集群:通过多个Broker节点以及镜像队列、Quorum Queue来实现任意节点宕机的情况下也不会影响消息的正常传递。
2.消息路由的灵活性
RabbitMQ提供四种交换机类型,支持不同的消息分发逻辑:
- Direct:精确匹配,适合点对点通信(如订单通知)
- Fanout:广播,适合群发(如系统公告)
- Topic:模糊匹配,适合多主题订阅(如日志分类)
- Headers:基于消息属性匹配,适合复杂属性过滤(如根据用户角色分发消息)
这使得RabbitMQ可以应对大部分复杂业务场景。
3.不同系统之间实现资源隔离
RabbitMQ可通过Virtual Host(虚拟主机)技术,来创造一个独立的消息空间,存储对应的交换机、队列以及用户权限,确保不同Virtual Host之间的资源互不干扰。
这避免了集群模式下队列名称重复、权限泄露等资源冲突风险,提高了集群的资源利用率。
4.高可用的集群设计
RabbitMQ支持集群架构,并通过队列副本实现高可用:
- 镜像队列:将Queue复制到主节点+从节点(如1主2从),主节点处理读写请求,从节点同步消息;主节点宕机后,从节点自动接管(最终一致)。
- Quorum Queue:基于Raft协议的强一致队列,每个Queue有多个副本,消息需被多数节点确认后才会被消费者接收;主节点宕机后,从节点自动选举为新主节点(强一致)。
这里的队列同步实际上和的副本同步思想很相似,镜像队列是主节点收到数据后就立即向生产者返回ACK,而Quorum Queue则是在副本全部同步完成之后才返回ACK,因此前者存在丢失数据的风险(主节点宕机导致未同步的消息丢失)。
(二)缺点
1.高场景下的性能瓶颈
RabbitMQ的吞吐量(消息/秒)远低于Kafka、RocketMQ等同类产品(如Kafka可轻松达到百万级/秒,而RabbitMQ通常在十万级/秒以内),难以应对大规模、高并发的消息场景。
之所以会这样,主要是因为以下几个原因:
- 存储机制限制:RabbitMQ的队列采用每个队列单独存储的模式,高吞吐量下,多个队列的磁盘IO会相互竞争,导致IO瓶颈(随机写)。
- Erlang虚拟机:RabbitMQ基于Erlang开发,Erlang的BEAM虚拟机虽然适合高并发小任务,但对于大流量数据传输),其性能不如JVM高效。
- 镜像队列同步开销:镜像队列需要将消息异步同步到多个从节点,高吞吐量下会占用大量网络带宽和磁盘IO。
- 灵活性换取高吞吐:消息会在发送到队列之前由交换机进行路由,可能会造成消息堆积。
2.资源占用空间较大
RabbitMQ每个队列都采用单独存储的模式,在集群模式下的资源消耗尤为明显:
- 内存占用:Erlang的BEAM虚拟机本身需要大量内存(如单个RabbitMQ节点默认占用数百MB内存),加上队列的内存缓存,高并发下容易触发内存流控(RabbitMQ会暂停接收消息,直到内存占用下降)。
- 网络带宽:镜像队列的异步同步需要占用大量网络带宽(如1主2从的镜像队列,每发送1条消息需要同步2次),跨节点的消息传输会加剧带宽消耗。
- 磁盘空间:镜像队列的多副本存储会导致磁盘空间翻倍(如3个副本的队列,磁盘空间是单副本的3倍),Quorum Queue的Raft日志也会占用额外的磁盘空间。
3.不适合架构
RabbitMQ的设计基于小规模、灵活性以及实时性,是不适合使用分布式架构的。
每个队列单独存储,无法线性扩展,当管理当前队列的Broker宕机后,该队列会变得完全不可用,想要扩展只能添加相同功能的队列进行绑定,但这样不仅增加了丢失消息的风险,也不符合业务逻辑的单一职责性。
而且队列与交换机的强绑定,每当新增节点都需要修改原有配置,导致扩展成本高且风险大。
四、总结
RabbitMQ的特性决定了其适合中小规模、实时性要求高、需要灵活路由、消息丢失零容忍的场景,不适合大规模高吞吐量、流处理场景。
1. 适合的场景
- **实时性要求高的场景:**如订单通知、即时通讯、物流状态更新等。RabbitMQ的解耦性和实时路由能确保消息及时传递,满足实时场景的需求。
- **需要灵活路由的场景:**如多主题日志分类、用户角色消息过滤、系统公告。RabbitMQ的四种交换机类型能灵活应对这些场景。
- **消息丢失零容忍的场景:**如金融交易的订单支付、账户余额变更等。通过四大机制确保消息不丢失,满足金融场景的强可靠要求。
- **多租户/资源隔离的场景:**如企业内部多系统共享RabbitMQ集群(如订单系统、库存系统、用户系统)。Virtual Host的资源隔离能避免系统间的资源冲突,提高集群的资源利用率。
- **中小规模并发的场景:**如电商的库存更新、优惠券发放、用户注册通知等。RabbitMQ的十万级/秒吞吐量能满足中小规模并发的需求,且可靠性机制能确保消息不丢失。
2. 不适合的场景
- **大规模高吞吐量场景:**如日志收集、大数据同步、用户行为数据采集等。Kafka的百万级/秒吞吐量更适合这些场景,而RabbitMQ的性能瓶颈会导致消息堆积。
- **流处理/复杂数据分析场景:**如实时用户行为分析、实时推荐系统等。RabbitMQ缺乏原生的流处理支持,需依赖第三方工具(如Flink),增加系统复杂度。
- **对资源占用敏感的场景:**如小型微服务(资源有限的容器环境)。RabbitMQ的高资源占用会导致资源紧张,影响微服务的性能。
码文不易、留个赞再走吧
原文链接: 带你轻松学习RabbitMQ 作者: Yilena
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时










