RabbitMQ面试题是Java面试经常问到的话题,今天给大家总结了一份RabbitMQ面试题及答案@mikechen
RabbitMQ是什么?
RabbitMQ是一个开源的AMQP实现,服务器端用Erlang语言编写,支持多种客户端。
RabbitMQ的特征?
RabbitMQ具有高度可靠性、灵活的消息路由、消息持久性、集群支持、可扩展性等特性。
RabbitMQ的技术架构?
RabbitMQ的技术架构如下图所示:
1.生产者(Publisher)
发消息到RabbitMQ中的(Exchange)交换机上。
2.交换机(Exchange)
和生产者建立连接并接收生产者发来的消息
3.消费者(Consumer)
监听RabbitMQ中的(Queue)队列中的消息
4.队列(Queue)
Exchange将消息发送到指定的Queue中,Queue和消费者进行交互
5.路由(Routes)
交换机转发消息到队列的规则
RabbitMQ中的Exchange类型?
Direct、Fanout、Topic和Headers。
为什么要使用RabbitMQ?
1.解耦:系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦。
2.异步:将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度。
3.削峰:并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常。
RabbitMQ有哪些特点?
1.可靠性:
RabbitMQ使用一些机制来保证可靠性, 如持久化、传输确认及发布确认等。
2.灵活的路由 :
在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能, RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个 交换器绑定在一起, 也可以通过插件机制来实现自己的交换器。
3.扩展性:
多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展 集群中节点。
4.高可用性
队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队 列仍然可用。
5.多种协议:
RabbitMQ除了原生支持AMQP协议,还支持STOMP, MQTT等多种消息 中间件协议。
6.多语言客户端
RabbitMQ 几乎支持所有常用语言,比如 Java、 Python、 Ruby、 PHP、 C#、 JavaScript 等。
RabbitMQ 的缺点
1.系统可用性降低
系统引入的外部依赖越多,越容易挂掉,本来你就是A系统调用BCD三个系统的接口就好了,本来ABCD四个系统好好的,没啥问题,你偏加个MQ进来,万一MQ挂了咋整?MQ挂了,整套系统崩溃了,你不就完了么。
2.系统复杂性提高
硬生生加个MQ进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?
3.一致性问题
A系统处理完了直接返回成功了,本来都以为你这个请求就成功了;但是问题是,BD两个系统写库成功了,结果C系统写库失败了,咋整?你这数据就不一致了。
AMQP 是什么?
AMQP(Advanced Message Queuing Protocol)是一种用于应用程序之间进行消息通信的开放标准协议,RabbitMQ 就是 AMQP 协议的 Erlang 的实现。
一些关键的AMQP概念包括:
- 生产者(Producer): 生成并发送消息的应用程序。
- 消费者(Consumer): 接收并处理消息的应用程序。
- Exchange(交换机): 用于接收生产者发送的消息,并将其路由到一个或多个队列。
- Queue(队列): 存储消息的地方,消费者从队列中获取消息进行处理。
- Binding(绑定): 定义了交换机和队列之间的关系,规定了如何将消息从交换机路由到队列。
- Broker(代理): 实现AMQP协议的消息中间件,负责接收、存储、路由和传递消息。
什么是死信队列?
死信队列(Dead Letter Queue,简称DLQ)是消息队列中的一种特殊队列,用于存储无法被正常消费和处理的消息。
通常,死信队列是为了处理那些由于某种原因无法被消费者成功处理的消息,例如:
- 消息过期: 当消息的生存周期超过预定的时间限制时,可能被视为过期而成为死信。
- 消息被拒绝: 如果消费者拒绝接受消息,并且消息不可重新投递,这些消息可能被发送到死信队列。
- 消息在队列中达到最大重试次数: 如果消息在队列中被重新投递的次数达到一定限制,可能被标记为死信。
- 未找到匹配的队列: 当消息无法路由到任何队列时,也可能被认为是死信。
RabbitMQ 有哪些工作模式?
RabbitMQ提供了6种模式:
1、简单模式
生产者,一个队列一个或多个消费者,当多个消费者同时监听一个队列时,他们并不能同时消费一条消息,而是随机消费消息,即一个队列中一条消息,只能被一个消费者消费。
2、主题模式(topic)
生产者,一个交换机(topicExchange),模糊匹配路由规则,多个队列,多个消费者。
3、订阅与发布模式(fanout)
生产者,一个交换机(fanoutExchange),没有路由规则,多个队列,多个消费者。生产者将消息不是直接发送到队列,而是发送到X交换机,然后由交换机发送给两个队列,两个消费者各自监听一个队列,来消费消息。
4、路由模式(direct)
生产者,一个交换机(directExchange),路由规则,多个队列,多个消费者。主要根据定义的路由规则决定消息往哪个队列发送。
5、RPC模式
对于RPC请求,客户端发送一条带有两个属性的消息:replyTo,设置为仅为请求创建的匿名独占队列,和correlationId,设置为每个请求的唯一id值。请求被发送到rpc_queue队列。RPC工作进程在队列上等待请求。当一个请求出现时,它执行任务,并使用replyTo字段中的队列将结果发回客户机。客户机在回应消息队列上等待数据。当消息出现时,它检查correlationId属性。如果匹配请求中的值,则向程序返回该响应数据。
6、工作队列
注释:默认情况下,RabbitMQ将按顺序将每条消息发送给下一个消费者,平均而言,每个消费者将获得相同数量的消息,这种分发消息的方式称为循环法。
RabbitMQ 如何保证消息的可靠性?
这里的可靠性分为三种:
- 消息到 MQ 的过程中搞丢
- MQ 自己搞丢
- MQ 到消费过程中搞丢
所以针对这三类的情况,如何保证可靠性呢?
生产者到 RabbitMQ,采用事务机制和 Confirm 机制,注意:事务机制和 Confirm 机制是互斥的,两者不能共存,会导致 RabbitMQ 报错。
RabbitMQ 自身,采用比如:持久化、集群、普通模式、镜像模式。
RabbitMQ 到消费者,采用比如:basicAck 机制、死信队列、消息补偿机制
RabbitMQ 消费者接收消息过程?
1.Producer先连接到Broker,建立连接Connection,开启一个信道(Channel)。
2.向Broker请求消费响应的队列中消息,可能会设置响应的回调函数。
3.等待Broker回应并投递相应队列中的消息,接收消息。
4.消费者确认收到的消息,ack。
5.RabbitMq从队列中删除已经确定的消息。
6.关闭信道。
7.关闭连接。
什么是延迟队列?
延迟队列指的是存储对应的延迟消息,消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。
RabbitMQ 怎么实现延迟队列?
RabbitMQ本身是没有延迟队列的,要实现延迟消息,一般有两种方式:
通过RabbitMQ本身队列的特性来实现,需要使用RabbitMQ的死信交换机(Exchange)和消息的存活时间TTL(Time To Live)。
在RabbitMQ 3.5.7及以上的版本提供了一个插件(rabbitmq-delayed-message-exchange)来实现延迟队列功能。同时,插件依赖Erlang/OPT 18.0及以上。
也就是说,AMQP 协议以及RabbitMQ本身没有直接支持延迟队列的功能,但是可以通过TTL和DLX模拟出延迟队列的功能。
RabbitMQ中消息可能有的几种状态?
- alpha: 消息内容(包括消息体、属性和 headers) 和消息索引都存储在内存中 ;
- beta: 消息内容保存在磁盘中,消息索引保存在内存中;
- gamma: 消息内容保存在磁盘中,消息索引在磁盘和内存中都有 ;
- delta: 消息内容和索引都在磁盘中 。
如何保证 RabbitMQ 消息的顺序性?
拆分多个 queue(消息队列),每个 queue(消息队列) 一个 consumer(消费者),就是多一些 queue (消息队列)而已,确实是麻烦点;
或者就一个 queue (消息队列)但是对应一个 consumer(消费者),然后这个 consumer(消费者)内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
如何保证RabbitMQ消息队列的高可用?
RabbitMQ 有三种模式:
1.单机模式
单机模式:就是demo级别的,一般就是你本地启动了玩玩儿的,没人生产用单机模式
2.普通集群模式
普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。
3.镜像集群模式
镜像集群模式:这种模式才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据(元数据指RabbitMQ的配置数据)还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。
RabbitMQ和Kafka的区别是什么?
RabbitMQ更适用于消息的可靠传递,支持灵活的消息路由,而Kafka更适用于流式处理和大规模数据的高吞吐。
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》