RabbitMQ面试题整理
1.RabbitMQ是什么?
RabbitMQ是实现了高级消息队列协议(AMQP
)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的。
2.RabbitMQ 的使用场景有哪些
抢购活动,削峰填谷,防止系统崩塌。
延迟信息处理,比如 10 分钟之后给下单未付款的用户发送邮件提醒。
解耦系统,对于新增的功能可以单独写模块扩展,比如用户确认评价之后,新增了给用户返积分的功能,这个时候不用在业务代码里添加新增积分的功能,只需要把新增积分的接口订阅确认评价的消息队列即可,后面再添加任何功能只需要订阅对应的消息队列即可。
3.RabbitMQ的特点?
可靠性:使用持久化和ACK消息确认机制来保证可靠性。
扩展性:多个RabbitMQ节点可以组成一个集群,可以根据实际业务需求动态扩展节点。
高可用性:队列可以在集群的基础上设置镜像,使得在部分节点失效的情况下保证队列仍旧可用。
灵活性:RabbitMQ几乎不受编程语言的限制,支持如Java、Python等常用编程语言。
4.RabbitMQ有哪些重要的角色
RabbitMQ 中重要的角色有:生产者、消费者和代理:
生产者:消息的创建者,负责创建和推送数据到消息服务器;
消费者:消息的接收方,用于处理数据和确认消息;
代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色。
5.RabbitMQ 有哪些重要的组件
ConnectionFactory(连接管理器):应用程序与 Rabbit 之间建立连接的管理器,程序代码中使用。
Channel(信道):消息推送使用的通道。
Exchange(交换器):用于接受、分配消息。
Queue(队列):用于存储生产者的消息。
RoutingKey(路由键):用于把生成者的数据分配到交换器上。
BindingKey(绑定键):用于把交换器的消息绑定到队列上。
6. RabbitMQ 中 vhost 的作用是什么
vhost:每个 RabbitMQ 都能创建很多 vhost,我们称之为虚拟主机,每个虚拟主机其实都是 mini 版的 RabbitMQ,它拥有自己的队列,交换器和绑定,拥有自己的权限机制。
7.RabbitMQ 的消息是怎么发送的
首先客户端必须连接到 RabbitMQ 服务器才能发布和消费消息,客户端和 rabbit server 之间会创建一个 tcp 连 接,一旦 tcp 打开并通过了认证(认证就是你发送给 rabbit 服务器的用户名和密码),你的客户端和 RabbitMQ 就创建了一条 amqp 信道(channel),信道是创建在“真实” tcp 上的虚拟连接,amqp 命令都是通过信道发送 出去的,每个信道都会有一个唯一的 id,不论是发布消息,订阅队列都是通过这个信道完成的。
8.RabbitMQ 怎么保证消息的稳定性
生产者到RabbitMQ:事务机制和Confirm机制,注意:事务机制和 Confirm 机制是互斥的,两者不能共存,会导致 RabbitMQ 报错。
RabbitMQ自身:持久化、普通集群模式、镜像集群模式。
RabbitMQ到消费者:basicAck机制、死信队列、消息补偿机制。
9.RabbitMQ 怎么避免消息丢失
把消息持久化磁盘,保证服务器重启消息不丢失。
每个集群中至少有一个物理磁盘,保证消息落入磁盘。
10.RabbitMQ 要保证消息持久化成功的条件有哪些
1.声明队列必须设置持久化 durable 为 true.
2.消息推送投递模式必须设置持久化,deliveryMode 设置为 2(持久)。
3.消息已经到达持久化交换器。
4.消息已经到达持久化队列。
前两步为持久化操作的两个步骤,以上四个条件都满足才能保证消息持久化成功。
11.RabbitMQ 持久化有什么缺点
持久化的缺点就是降低了服务器的吞吐量,因为使用的是磁盘而非内存存储。可以使用 SSD 固态硬盘代替磁盘来尽可能减轻持久化带来的吞吐量问题。
12.RabbitMQ 有几种广播类型
direct(默认方式):最基础最简单的模式,发送方把消息发送给订阅方,如果有多个订阅者,默认采取轮询的方式进行消息发送。
headers:与 direct 类似,只是性能很差,此类型几乎用不到。
fanout:分发模式,把消费分发给所有订阅者。
topic:匹配订阅模式,使用正则匹配到消息队列,能匹配到的都能接收到。
13.RabbitMQ 怎么实现延迟消息队列
AMQP协议和RabbitMQ队列本身没有直接支持延迟队列功能,但是可以通过以下特性模拟出延迟队列的功能。
1、Time To Live(TTL)
RabbitMQ可以针对Queue设置x-expires 或者 针对Message设置 x-message-ttl,来控制消息的生存时间,如果超时(两者同时设置以最先到期的时间为准),则消息变为dead letter(死信)。
2、Dead Letter Exchanges(DLX)
RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,如果队列内出现了dead letter,则按照这两个参数重新路由转发到指定的队列。
14.死信队列?
DLX,全称为 Dead-Letter-Exchange,死信交换器,死信邮箱。当消息在一个队列中变成死信 (dead message) 之后,它能被重新被发送到另一个交换器中,这个交换器就是 DLX,绑定 DLX 的队列就称之为死信队列。
15.导致的死信的几种原因?
- 消息被拒(Basic.Reject /Basic.Nack) 且 requeue = false。
- 消息TTL过期。
- 队列满了,无法再添加。
16.RabbitMQ 集群有什么用
集群主要有以下两个用途:
高可用:某个服务器出现问题,整个 RabbitMQ 还可以继续使用;
高容量:集群可以承载更多的消息量
17.RabbitMQ 节点的类型有哪些
磁盘节点:消息会存储到磁盘。
内存节点:消息都存储在内存中,重启服务器消息丢失,性能高于磁盘类型。
18.RabbitMQ 集群搭建需要注意哪些问题
各节点之间使用“–link”连接,此属性不能忽略。
各节点使用的 erlang cookie 值必须相同,此值相当于“秘钥”的功能,用于各节点的认证。
整个集群中必须包含一个磁盘节点。
保证各个节点 erlang 版本一致:RabbitMQ 基于 erlang 语言,必须保证 各个节点 erlang 版本完全一致。
可以跨操作系统建立集群。
19.RabbitMQ 每个节点是其他节点的完整拷贝吗为什么
不是,原因有以下两个:
存储空间的考虑:如果每个节点都拥有所有队列的完全拷贝,这样新增节点不但没有新增存储空间,反而增加了更多的冗余数据;
性能的考虑:如果每条消息都需要完整拷贝到每一个集群节点,那新增节点并没有提升处理消息的能力,最多是保持和单节点相同的性能甚至是更糟。
20.RabbitMQ 集群中唯一一个磁盘节点崩溃了会发生什么情况
如果唯一磁盘的磁盘节点崩溃了,不能进行以下操作:
- 不能创建队列
- 不能创建交换器
- 不能创建绑定
- 不能添加用户
- 不能更改权限
- 不能添加和删除集群节点
唯一磁盘节点崩溃了,集群是可以保持运行的,但你不能更改任何东西。
21.RabbitMQ 对集群节点停止顺序有要求吗
RabbitMQ 对集群的停止的顺序是有要求的,应该先关闭内存节点,最后再关闭磁盘节点。如果顺序恰好相反的话, 可能会造成消息的丢失。
22.交换器无法根据自身类型和路由键找到符合条件队列时,有哪些处理?
mandatory: true 返回消息给生产者。
mandatory: false 直接丢弃。
23.延迟队列?
存储对应的延迟消息,指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。
24.优先级队列?
优先级高的队列会先被消费。
可以通过x-max-priority参数来实现。
当消费速度大于生产速度且Broker没有堆积的情况下,优先级显得没有意义。
25.事务机制?
RabbitMQ 客户端中与事务机制相关的方法有三个:
channel.txSelect 用于将当前的信道设置成事务模式。
channel.txCommit 用于提交事务 。
channel.txRollback 用于事务回滚,如果在事务提交执行之前由于 RabbitMQ 异常崩溃或者其他原因抛出异常,通过txRollback来回滚。
26.发送确认机制?
生产者把信道设置为confirm确认模式,设置后,所有再改信道发布的消息都会被指定一个唯一的ID,一旦消息被投递到所有匹配的队列之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(包含消息的唯一ID),这样生产者就知道消息到达对应的目的地了。
27.消费者某些原因无法处理当前接受的消息如何来拒绝?
channel .basicNack channel .basicReject
28.消息传输保证层级?
At most once: 最多一次。消息可能会丢失,但不会重复传输。
At least once: 最少一次。消息绝不会丢失,但可能会重复传输。
Exactly once: 恰好一次,每条消息肯定仅传输一次。
29.队列结构?
通常由以下两部分组成?
rabbit_amqqueue_process:负责协议相关的消息处理,即接收生产者发布的消息、向消费者交付消息、处理消息的确认(包括生产端的 confirm和消费端的 ack) 等。
backing_queue:是消息存储的具体形式和引擎,并向 rabbit amqqueue process提供相关的接口以供调用,完成消息的存储以及可能的持久化工作等。
30.RabbitMQ中消息可能有的几种状态?
alpha: 消息内容(包括消息体、属性和 headers) 和消息索引都存储在内存中 。
beta: 消息内容保存在磁盘中,消息索引保存在内存中。
gamma: 消息内容保存在磁盘中,消息索引在磁盘和内存中都有 。
delta: 消息内容和索引都在磁盘中 。
31.如何保证RabbitMQ消息队列的高可用?
RabbitMQ 有三种模式:单机模式,普通集群模式,镜像集群模式。
单机模式:就是demo级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模式
普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。
镜像集群模式:这种模式,才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据(元数据指RabbitMQ的配置数据)还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。
32. RabbitMQ有什么优缺点?
**优点:**解耦、异步、削峰;
**缺点:**可能会降低系统的稳定性:在系统的业务功能和访问量需求足够的时候强行加入 RabbitMQ,如果消息队列出现问题,整个系统都会受到影响。因此,随意使用 RabbitMQ,可能会导致系统可用性降低。
增加了系统的复杂性:加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
33. 如何保证RabbitMQ不被重复消费?
先说为什么会重复消费:正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除;
但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。
针对以上问题,一个解决思路是:保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响;保证消息等幂性;
比如:在写入消息队列的数据做唯一标识,消费消息时,根据唯一标识判断是否消费过;