1. 什么是MQ?什么是RabbitMQ?
MQ,中文是消息队列(MessageQueue),字面来看就是存放消息的队列。也就是事件驱动架构中的Broker。
RabbitMQ采用 AMQP 高级消息队列协议的一种消息队列技术,最大的特点就是消费并不需要确保提供方存在,实现了服务之间的高度解耦。
2. 几种常见MQ的对比
RabbitMQ | ActiveMQ | RocketMQ | Kafka | |
---|---|---|---|---|
公司/社区 | Rabbit | Apache | 阿里 | Apache |
开发语言 | Erlang | Java | Java | Scala&Java |
协议支持 | AMQP,XMPP,SMTP,STOMP | OpenWire,STOMP,REST,XMPP,AMQP | 自定义协议 | 自定义协议 |
可用性 | 高 | 一般 | 高 | 高 |
单机吞吐量 | 一般 | 差 | 高 | 非常高 |
消息延迟 | 微秒级 | 毫秒级 | 毫秒级 | 毫秒以内 |
消息可靠性 | 高 | 一般 | 高 | 一般 |
- 追求可用性:Kafka、 RocketMQ 、RabbitMQ
- 追求可靠性:RabbitMQ、RocketMQ
- 追求吞吐能力:RocketMQ、Kafka
- 追求消息低延迟:RabbitMQ、Kafka
3. 为什么要使用RabbitMQ?
- 在分布式系统下具备异步,削峰,负载均衡等一系列高级功能
- 拥有持久化的机制,进程消息,队列中的信息也可以保存下来
- 实现消费者和生产者之间的解耦
- 对于高并发场景下,利用消息队列可以使得同步访问变为串行访问达到一定量的限流,利于数据库的操作
- 可以使用消息队列达到异步下单的效果,排队中,后台进行逻辑下单
4. RabbitMQ特点?
-
可靠性
RabbitMQ使用一些机制来保证可靠性, 如持久化、传输确认及发布确认等
-
灵活的路由
在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能, RabbitMQ 己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个 交换器绑定在一起, 也可以通过插件机制来实现自己的交换器
-
扩展性
多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展集群中节点
-
高可用性
队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队列仍然可用
-
多种协议
RabbitMQ除了原生支持AMQP协议,还支持STOMP, MQTT等多种消息中间件协议
-
多语言客户端
RabbitMQ 几乎支持所有常用语言,比如 Java、 Python、 Ruby、 PHP、 C#、 JavaScript 等
-
管理界面
RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的节点等
-
支持跟踪机制
如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么
5. AMQP是什么?
是具有现代特征的二进制协议。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。总而言之,是一个进程间传递异步消息的网络协议。
6. AMQP三层协议?
-
Module Layer
协议最高层,主要定义了一些客户端调用的命令,客户端可以用这些命令实现自己的业务逻辑
-
Session Layer
中间层,主要负责客户端命令发送给服务器,再将服务端应答返回客户端,提供可靠性同步机制和错误处理
-
Transport Layer
最底层,主要传输二进制数据流,提供帧的处理、信道服用、错误检测和数据表示等
7. AMQP模型的几大组件?
- 交换器 (Exchange):消息代理服务器中用于把消息路由到队列的组件
- 队列 (Queue):用来存储消息的数据结构,位于硬盘或内存中
- 绑定 (Binding):一套规则,告知交换器消息应该将消息投递给哪个队列
8. 说说生产者Producer和消费者Consumer?
-
生产者
-
消息生产者,就是投递消息的一方
-
消息一般包含两个部分:消息体(payload)和标签(Label)
-
-
消费者
- 消费消息,也就是接收消息的一方
- 消费者连接到RabbitMQ服务器,并订阅到队列上。消费消息时只消费消息体,丢弃标签
9. RabbitMQ交换机类型?
- Direct Exchange(直连交换机)
- Fanout Exchange(扇型交换机)
- Topic Exchange(主题交换机)
- Headers Exchange(头交换机)
10. 交换机的作用是什么?
- 接收publisher发送的消息
- 将消息按照规则路由到与之绑定的队列
- 不能缓存消息,路由失败,消息丢失
- FanoutExchange的会将消息路由到每个绑定的队列
11. 描述下Direct交换机与Fanout交换机的差异?
- Fanout交换机将消息路由给每一个与之绑定的队列
- Direct交换机根据RoutingKey判断路由给哪个队列
- 如果多个队列具有相同的RoutingKey,则与Fanout功能类似
12. 描述下Direct交换机与Topic交换机的差异?
- Topic交换机接收的消息RoutingKey必须是多个单词,以
**.**
分割 - Topic交换机与队列绑定时的bindingKey可以指定通配符
- #:代表0个或多个词
- *:代表1个词
13. 使用RabbitMQ的场景?
- 服务间异步通信
- 顺序消费
- 定时任务
- 请求削峰
14. 如何确保RabbitMQ消息的可靠性?
- 开启生产者确认机制,确保生产者的消息能到达队列
- 开启持久化功能,确保消息未消费前在队列中不会丢失
- 开启消费者确认机制为auto,由spring确认消息处理成功后完成ack
- 开启消费者失败重试机制,并设置MessageRecoverer,多次重试失败后将消息投递到异常交换机,交由人工处理
15. 什么是死信?
当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter):
- 消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数设置为false
- 消息是一个过期消息,超时无人消费
- 要投递的队列消息满了,无法投递
如果这个包含死信的队列配置了dead-letter-exchange属性,指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机称为死信交换机(Dead Letter Exchange,检查DLX)。
如图,一个消息被消费者拒绝了,变成了死信:
因为simple.queue绑定了死信交换机 dl.direct,因此死信会投递给这个交换机:
如果这个死信交换机也绑定了一个队列,则消息最终会进入这个存放死信的队列:
另外,队列将死信投递给死信交换机时,必须知道两个信息:
- 死信交换机名称
- 死信交换机与死信队列绑定的RoutingKey
这样才能确保投递的消息能到达死信交换机,并且正确的路由到死信队列。
16. 什么样的消息会成为死信?
- 消息被消费者reject或者返回nack
- 消息超时未消费
- 队列满了
17. 死信交换机的使用场景是什么?
- 如果队列绑定了死信交换机,死信会投递到死信交换机
- 可以利用死信交换机收集所有消费者处理失败的消息(死信),交由人工处理,进一步提高消息队列的可靠性
18. 消息超时的两种方式是?
- 给队列设置ttl属性,进入队列后超过ttl时间的消息变为死信
- 给消息设置ttl属性,队列接收到消息超过ttl时间后变为死信
19. 如何实现发送一个消息20秒后消费者才收到消息?
- 给消息的目标队列指定死信交换机
- 将消费者监听的队列绑定到死信交换机
- 发送消息时给消息设置超时时间为20秒
20. 什么是延迟队列?
利用TTL结合死信交换机,我们实现了消息发出后,消费者延迟收到消息的效果。这种消息模式就称为延迟队列(Delay Queue)模式。
21. 延迟队列的使用场景包括?
- 延迟发送短信
- 用户下单,如果用户在15 分钟内未支付,则自动取消
- 预约工作会议,20分钟后自动通知所有参会人员
22. 发送消息到DelayExchange的流程?
- 接收消息
- 判断消息是否具备x-delay属性
- 如果有x-delay属性,说明是延迟消息,持久化到硬盘,读取x-delay值,作为延迟时间
- 返回routing not found结果给消息发送者
- x-delay时间到期后,重新投递消息到指定队列
23. 延迟队列插件的使用步骤包括哪些?
- 声明一个交换机,添加delayed属性为true
- 发送消息时,添加x-delay头,值为超时时间
24. 解释一下消息堆积问题?
当生产者发送消息的速度超过了消费者处理消息的速度,就会导致队列中的消息堆积,直到队列存储消息达到上限。之后发送的消息就会成为死信,可能会被丢弃,这就是消息堆积问题。
25. 怎么解决消息堆积问题?
- 队列上绑定多个消费者,提高消费速度
- 提高单个消费者的性能
- 使用惰性队列,可以再mq中保存更多消息
26. 惰性队列有什么特征?
从RabbitMQ的3.6.0版本开始,就增加了Lazy Queues的概念,也就是惰性队列。惰性队列的特征如下:
- 接收到消息后直接存入磁盘而非内存
- 消费者要消费消息时才会从磁盘中读取并加载到内存
- 支持数百万条的消息存储
27. 惰性队列的优点?
- 基于磁盘存储,消息上限高
- 没有间歇性的page-out,性能比较稳定
28. 惰性队列的缺点?
- 基于磁盘存储,消息时效性会降低
- 性能受限于磁盘的IO
29. MQ普通集群的结构和特征?
- 会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息。
- 当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回。
- 队列所在节点宕机,队列中的消息就会丢失。
30. MQ镜像集群的结构和特征?
- 交换机、队列、队列中的消息会在各个mq的镜像节点之间同步备份。
- 创建队列的节点被称为该队列的主节点,备份到的其它节点叫做该队列的镜像节点。
- 一个队列的主节点可能是另一个队列的镜像节点。
- 所有操作都是主节点完成,然后同步给镜像节点。
- 主宕机后,镜像节点会替代成新的主
31. MQ仲裁队列的集群特征?
- 与镜像队列一样,都是主从模式,支持主从数据同步。
- 使用非常简单,没有复杂的配置。
- 主从同步基于Raft协议,强一致。