RabbitMQ 消息中间件/消息队列
[TOC]
1、消息中间件
1.1 简介
消息队列(Message Queue,简称 MQ)是一种用于跨进程或跨系统的异步通信机制。它允许不同的服务、应用程序或进程之间传递消息,从而实现解耦和高效的任务处理。消息队列通常用于异步处理、分布式系统、负载均衡等场景。
消息传递指的是程序之间通过在消息中发送数据进行通信。
当下主流的消息中间件有RabbitMQ、Kafka、ActiveMQ、RocketMQ等
1.2 异步处理
场景说明:用户注册账号以后,需要发送注册成功邮件和注册成功短信,传统的做法有两种:
1 | 1.串行的方式; |
1.2.1 串行方式
将注册信息写入数据库后,发送注册邮件,再发送注册短信,以上三个任务全部完成后才返回给客户端。这有一个问题是,邮件,短信并不是必须的,它只是一个通知,而这种做法让客户端等待没有必要等待的东西。

1.2.2 并行方式
将注册信息写入数据库后,发送邮件的同时,发送短信,以上三个任务完成后,返回给客户端,并行的方式能提高处理的时间。

假设三个业务节点分别使用50ms,串行方式使用时间150ms,并行使用时间100ms。虽然并性已经提高的处理时间,但是,前面说过邮件和短信对我正常的使用网站没有任何影响,客户端没有必要等着其发送完成才显示注册成功,应该是写入数据库后就返回。
1.2.3 消息队列
引入消息队列后,把发送邮件,短信不是必须的业务逻辑异步处理。

由此可以看出,引入消息队列后,用户的响应时间就等于写入数据库的时间+写入消息队列的时间(可以忽略不计),引入消息队列后处理后,响应时间是串行的3倍,是并行的2倍。
2、作用
2.1 消息中间件主要作用
- 冗余(存储)
- 消息持久化功能,将消息存储在可靠的介质中,确保在系统故障或崩溃时,消息不会丢失。
- 扩展性
- 消息中间件支持系统的水平扩展。通过添加更多的生产者(Producers)和消费者(Consumers),可以处理更大规模的数据量和流量。
- 可恢复性
- 具有内建的故障恢复机制,能够在系统组件出现故障时进行恢复。例如,当某个消费者崩溃后重新启动时,它可以从上次处理的消息位置继续处理未完成的消息,从而实现故障恢复。
- 缓冲
- 在生产者和消费者之间提供缓冲作用。生产者可以以自己的速度发送消息,而消费者可以以自己的速度处理消息,这种缓冲机制帮助平滑突发的流量高峰,防止系统过载。
- 异步通信
- 允许系统之间进行异步通信,生产者发送消息后不需要等待消费者处理完毕,这样可以提高系统的并发性和响应速度。异步通信模式下,生产者和消费者可以独立地进行处理,提升整体系统的效率。
- 削峰
- 消息队列中的常用场景,一般在秒杀或抢购活动中使用广泛。一般会因为流量过大,应用系统配置承载不了这股瞬间流量,导致系统直接挂掉,即传说中的“宕机”现象。为解决这个问题,我们会将那股巨大的流量拒在系统的上层,即将其转移至 MQ 而不直接涌入我们的接口。
- 解耦(耦合性)
- 降低应用与应用间的耦合性
3、消息中间件的两种模式
1、P2P模式 Rabbitmq
P2P模式包含三个角色:消息队列(Queue)、发送者(Sender)、接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到它们被消费或超时。
P2P的特点:(点对点:Queue,不可重复消费)
- 每个消息只有一个消费者(Consumer),即一旦被消费,消息就不再在消息队列中存在
- 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行它不会影响到消息被发送到队列
- 接收者在成功接收消息之后需向队列应答成功
- 如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式
2、Pub/Sub模式(发布/订阅:Topic,可以重复消费)
Pub/Sub模式包含三个角色:主题(Topic)、发布者(Publisher)、订阅者(Subscriber) 。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
Pub/Sub的特点:
- 每个消息可以有多个消费者
- 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息
- 为了消费消息,订阅者必须保持运行的状态
- 如果希望发送的消息可以不被做任何处理、或者只被一个消费者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型
4、常用中间件介绍与对比
1、Kafka
Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点是追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量日志数据的互联网服务的数据收集业务。
2、RabbitMQ
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是异步通信、面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
Erlang是一种通用的面向并发的编程语言
AMQP(Advanced Message Queuing Protocol,高级消息队列协议)是一个开放的标准应用层协议,用于消息传递。AMQP 设计的初衷是为了实现跨平台的消息队列系统,确保不同的消息传递中间件能够互操作。
主要特性
- 异步消息传递:AMQP 支持异步消息传递,可以在发送和接收消息时不需要同步等待。
- 跨平台互操作性:AMQP 是一个开放标准,支持不同平台和编程语言的互操作。
- 可靠性:提供消息确认、持久化、事务等机制,确保消息不会丢失。
3、RocketMQ
RocketMQ是阿里开源的消息中间件,它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、消息推送、日志流式处理、binglog分发等场景。
RabbitMQ比Kafka可靠,Kafka更适合IO高吞吐的处理,一般应用在大数据日志处理或对实时性(少量延迟),可靠性(少量丢数据)要求稍低的场景使用,比如ELK日志收集。
2、RabbitMQ集群
1、RabbitMQ简介
RabbitMQ是Erlang开发的,集群非常方便,因为Erlang天生就是分布式语言,但其本身并不支持负载均衡,支持高并发,支持可扩展。支持AJAX,持久化,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。Ajax = 异步 JavaScript 和 XML
2、RabbitMQ 特点
- 可靠性
持久化:消息可以持久化到磁盘,确保在服务器重启后仍然可以恢复消息。- 确认机制:生产者和消费者可以收到消息传递和处理的确认,确保消息不会丢失。
扩展性
集群:RabbitMQ 可以配置为集群模式,多个节点共同工作,分担消息负载。- 分区交换:消息可以根据规则分发到不同的队列,实现负载均衡。
高可用性
镜像队列:队列可以配置为镜像队列,消息会在多个节点之间复制,确保其中一个节点故障时消息不会丢失。自动故障转移:在集群模式下,RabbitMQ 可以自动进行故障转移,保持系统的高可用性。
多语言客户端
- Java:通过 Spring AMQP、RabbitMQ Java Client 等库进行集成。
- 其他语言:如 .NET、JavaScript、Go、PHP 等都有对应的客户端库。
Web管理界面
- 提供了一个功能强大的 Web 管理界面,便于管理和监控
插件机制
- 通过简单的命令可以安装和启用插件。
- Management Plugin:提供 Web 管理界面。
- 其他插件:如延迟队列插件、安全认证插件等。
- 通过简单的命令可以安装和启用插件。
3、RabbitMQ模式
注意:RabbitMQ模式大概分为以下三种:
(1)单机模式。
(2)普通模式(默认的集群模式)。
(3)镜像模式(把需要的队列做成镜像队列,存在于多个节点,属于RabbiMQ的HA方案,在对业务可靠性要求较高的场合中比较适合)。要实现镜像模式,需要先搭建出普通集群模式,在这个模式的基础上再配置镜像模式以实现高可用。
4、了解集群中的基本概念:
RabbitMQ的集群节点包括内存节点、磁盘节点。顾名思义内存节点就是将所有数据放在内存,磁盘节点将数据放在磁盘。
一个rabbitmq集群中可以共享 user,vhost,queue,exchange等,所有的数据和状态都是必须在所有节点上复制。
1 | Broker: |

- 生产者发送消息:
- 生产者创建消息,并将其发送到 RabbitMQ 的某个交换机中。消息可以携带路由键,交换机会根据这个键和绑定规则将消息路由到相应的队列。
- 交换机路由消息:
- 交换机接收消息后,根据类型和绑定规则将消息路由到一个或多个队列中。如果没有找到匹配的队列,交换机会丢弃消息,或者根据配置返回给生产者。
- 消息进入队列:
- 一旦消息被路由到队列中,消息就会暂时存储在队列中,等待消费者处理。队列可以配置为持久化,以确保即使 RabbitMQ 服务崩溃,消息也不会丢失。
- 消费者接收消息:
- 消费者从队列中取走消息并进行处理。消息的分发可以通过轮询(Round Robin)分配给多个消费者,或者消费者可以从多个队列中获取消息进行处理。
- 消息确认:
- 消费者处理完消息后,会向 RabbitMQ 发送一个确认消息(ACK),告知消息已被成功处理。如果消费者在处理过程中失败,RabbitMQ 可以重新将消息投递给其他消费者或重新进入队列,这取决于队列的配置。
面试注意:集群中有两种节点
内存节点:只保存状态到内存(持久的queue的持久内容将被保存到磁盘中)磁盘节点:保存状态到内存和磁盘。—推荐
内存节点虽然不写入磁盘,但是它执行比磁盘节点要高。集群中,只需要一个磁盘节点来保存状态 就足够了。如果集群中只有内存节点,那么不能停止它们,否则所有的状态,消息等都会丢失。
5、普通集群准备环境
Rabbitmq官方最新rpm包下载地址:https://www.rabbitmq.com/install-rpm.html#downloads
1 | # rabbitmq 和 erlang兼容版本 |
三台机器都操作:
配置hosts文件;更改三台MQ节点的
主机名分别为rabbitmq-1、rabbitmq-2 和rabbitmq-3,然后修改hosts配置件1
2
3
4
5
6
7
8
9
10三台主机修改主机名
[root@rabbitmq-1 ~]# hostnamectl set-hostname rabbitmq-1
三台主机本地解析
[root@rabbitmq-1 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.50.138 rabbitmq-1
192.168.50.139 rabbitmq-2
192.168.50.140 rabbitmq-3三个节点配置安装rabbitmq软件
1 | 安装依赖 |
1 | 启动 |

默认:RabbitMQ web界面关闭
创建用户
1 | 注意:在一台机器操作 |
此处设置权限时注意'.*'之间需要有空格 三个'.*'分别代表了加载conf权限,read权限与write权限 例如:当没有给soho设置这三个权限前是没有权限查询队列,在ui界面也看不见
- 三台机器都操作:开启用户远程登录:
1 | 切换目录 |

1 | 三台机器都操作重启服务服务: |
查看端口

1 | 4369 -- erlang端口 |
!注意如果是云服务器,切记添加安全组端口放行。
访问:192.168.50.138:15672


这里需要注意:
rabbitmq默认管理员用户:guest 密码:guest
新添加的用户为:soho 密码:soso
6、开始部署集群三台机器都操作
1.首先创建好数据存放目录和日志存放目录:
3台机器都操作:
1 | 创建RabbitMQ数据存放处 |
2.拷erlang.cookie
Rabbitmq的集群是依附于erlang的集群来工作的,所以必须先构建起erlang的集群。Erlang的集群中各节点是经由各个cookie来实现的,这个cookie存放在/var/lib/rabbitmq/.erlang.cookie中,文件是400的权限。所以必须保证各节点cookie一致,不然节点之间就无法通信。
如果执行# rabbitmqctl stop_app 这条命令报错:需要执行
1 | 如果执行# rabbitmqctl stop_app 这条命令报错:需要执行 |
(官方在介绍集群的文档中提到过.erlang.cookie 一般会存在这两个地址:第一个是home/.erlang.cookie;第二个地方就是/var/lib/rabbitmq/.erlang.cookie。如果我们使用解压缩方式安装部署的rabbitmq,那么这个文件会在{home}目录下,也就是$home/.erlang.cookie。如果我们使用rpm等安装包方式进行安装的,那么这个文件会在/var/lib/rabbitmq目录下。)
1 | 查看Cookie值 |
.erlang.cookie文件是 Erlang 运行时系统用于节点之间的认证文件。在搭建 RabbitMQ 集群时,确保了集群中的各个节点可以相互通信和信任。每个节点在启动时都会检查 .erlang.cookie 文件的内容,只有拥有相同 cookie 值的节点才能成功地建立连接并进行通信。
3.将mq-2、mq-3作为内存节点加到mq-1节点集群中
1 | 在mq-2、mq-3执行如下命令: 停止节点,切记不是停止服务 |

1 | 如果有数据需要重置,没有则不用 |

注意查看回显,如果不是以上。就是错误;如果报错,重启rabbitmq服务
1 | 将两个节点加入集群,指定角色,添加到内存节点 |
4.查看集群状态
1 | 在RabbitMQ集群任意节点上执行 rabbitmqctl cluster_status来查看是否集群配置成功。在mq-1磁盘节点上面查看 |

1 | 每台机器显示出三台节点,表示已经添加成功! |
5.登录rabbitmq web管理控制台,创建新的队列
打开浏览器输入http://192.168.50.138:15672,
输入默认的Username:guest;输入默认的Password:guest
此时会发现之间创建的用户登录不了,这是因为我们修改了rabbitmq的数据目录,导致之前创建的用户消失了。
登录后出现如图所示的界面。

根据界面提示创建一条队列


7、RabbitMQ镜像集群配置
上面已经完成RabbitMQ默认集群模式,但并不保证队列的高可用性,队列内容不会复制。如果队列节点宕机直接导致该队列无法应用,只能等待重启,所以要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群里的每个节点,必须要创建镜像队列。
镜像队列是基于普通的集群模式的。
创建镜像集群:在任意一台机器操作
rabbitmq set_policy :设置策略
1 | [root@rabbitmq-1 ~]# rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' |
“^”匹配所有的队列, ha-all 策略名称为ha-all, ‘{“ha-mode”:”all”}’ 策略模式为 all 即复制到所有节点,包含新增节点。
再次查看队列已经同步到其他两台节点:

“^”匹配所有的队列, ha-all 策略名称为ha-all, ‘{“ha-mode”:”all”}’ 策略模式为 all 即复制到所有节点,包含新增节点。
1 | 设置策略介绍: |
则此时镜像队列设置成功。已经部署完成。将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态保持一致。
3、RabbitMQ面试题
1、消息队列的作用?
2、RabbitMQ有什么作用?
- 消息队列
- 将消息从发送方(生产者)传递到接收方(消费者)。通过消息队列,生产者和消费者可以异步通信,互不干扰。
- 异步处理
- 通过将任务封装成消息放入队列,应用程序可以实现异步处理,从而提高响应速度和处理效率。例如,Web 应用可以快速响应用户请求,同时在后台处理耗时的任务。
- 组件解耦
- 通过使用消息队列,系统的不同组件(服务或应用)可以互相解耦。这样,各组件可以独立开发、部署和扩展,而不必直接依赖于其他组件的实现细节。
- 负载均衡
- 当有多个消费者订阅同一个队列时,RabbitMQ 可以将消息分发给这些消费者,实现负载均衡,确保每个消费者处理的工作量大致均等。
- 高可用性
- RabbitMQ 支持集群模式和镜像队列,可以提供高可用性和故障恢复能力,确保在节点故障时系统依然可以正常工作。
- 灵活的路由
- RabbitMQ 通过交换器(Exchange)和绑定(Binding)机制,提供灵活的消息路由功能。可以根据不同的路由键、队列绑定和交换器类型,实现复杂的消息路由规则。
3、RabbitMQ的工作模式?
- 单节点模式
- 单节点模式是最简单的部署方式,适合小型应用或开发测试环境。
- 普通集群模式
- 普通集群模式包含多个 RabbitMQ 节点,节点之间可以共享消息队列,但消息本身不会被复制。
- 镜像模式
- 镜像模式是普通集群模式的扩展,增加了消息的高可用性。队列可以被镜像到集群中的多个节点上。
4、消息队列使用场景
- 任务队列
- 后台任务处理(例如发送电子邮件)
- 事件通知
- 分布式系统中组件之间的事件通知
- 数据流处理
- 实时数据流的处理和分析,例如日志收集和处理
- 负载分发
- 将消息负载分发给多个消费者,实现负载均衡和并行处理







