面试专题之——RabbitMQ

RabbitMQ有几种通信模式?

6种

1、简单模式:一个生产者,一个消费者,一个消息队列,不设置交换机,使用的默认交换机

2、工作队列模式:一个生产者,多个消费者,一个消息队列,不设置交换机,使用默认的交换机

3、发布订阅模式:将交换机和队列进行绑定,当消息发送到交换机时,交换机会将消息发送到绑定的队列

4、路由模式:将交换机和队列进行绑定,并且指定路由key,根据路由key将消息发送到相应的队列

5、通配符模式:与路由模式的不同就是路由key可以使用通配符

6、RPC模式

RabbitMQ如何保证生产者消息的可靠性?

生产者可以开启消息确认以及消息回执机制,开启后,我们发送一条消息RabbitMQ会根据是否发送成功返回ack与nack(可以手动配置同步异步),如果消息发送到了交换机返回ack,如果没发送到交换机则返回nack,交换机如果路由失败也会返回ack以及失败原因,我们可以根据返回的结果来决定消息的兜底措施,这样就就可以保证生产者消息的可靠性

RabbitMQ如何保证消费者的消息可靠性?

1、使用消息重试机制,配置模式、重试次数、重试等待时间等。重试次数耗尽之后根据配置的重试失败策略决定如何处理该消息,默认是直接丢弃,还有两种方式,一种是重试失败后重新入队,一种是重试失败后消息投递到指定交换机,后者更加优雅。例如消息重试多次还是失败,此时把该消息投递到指定的交换机,然后进行兜底措施,或通过发送邮件等方式告知相关人员

2、使用手动ack模式,如果消息成功消费则返回ack让MQ删除消息,如果失败则返回nack不让MQ删除消息

RabbitMQ保证消息的可靠性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1.生产者发送消息时可能因为网络问题导致消息没有到达交换机
使用RabbitMQ的publisher confirm机制:
- 生产者发送消息后,可以编写ConfirmCallback函数
- 消息成功到达交换机后,RabbitMQ会调用ConfirmCallback通知消息的发送者,返回ACK
- 消息如果未到达交换机,RabbitMQ也会调用ConfirmCallback通知消息的发送者,返回NACK
- 消息超时未发送成功也会抛出异常
2.消息到达交换机后,如果未能到达队列,也会导致消息丢失
使用RabbitMQ的publisher return机制
- 生产者可以定义ReturnCallback函数
- 消息到达交换机,未到达队列,RabbitMQ会调用ReturnCallback通知发送者,告知失败原因
3.消息到达队列后,MQ宕机也可能导致丢失消息
RabbitMQ提供了持久化功能,集群的主从备份功能
- 消息持久化,RabbitMQ会将交换机、队列、消息持久化到磁盘,宕机重启可以恢复消息
- 镜像集群,仲裁队列,都可以提供主从备份功能,主节点宕机,从节点会自动切换为主,数据依然在
4.消息投递给消费者后,如果消费者处理不当,也可能导致消息丢失
SpringAMQP基于RabbitMQ提供了消费者确认机制、消费者重试机制,消费者失败处理策略:
a.消费者的确认机制:
1.消费者处理消息成功,未出现异常时,Spring返回ACK给RabbitMQ,消息才被移除。
2.消费者处理消息失败,抛出异常,宕机,Spring返回NACK或者不返回结果,消息不被移除。
b.消费者重试机制:
默认情况下,消费者处理失败时,消息会再次回到MQ队列,然后投递给其它消费者。Spring提供的消费者重试机制,则是在处理失败后不返回NACK,而是直接在消费者本地重试。多次重试都失败后,则按照消费者失败处理策略来处理消息。避免了消息频繁入队带来的额外压力。
c.消费者失败策略:
1.当消费者多次本地重试失败时,消息默认会丢弃。
2.Spring提供了Republish策略,在多次重试都失败,耗尽重试次数后,将消息重新投递给指定的异常交换机,并且会携带上异常栈信息,帮助定位问题。

什么是死信消息?如何利用死信消息实现延迟队列?

死信消息就是消费失败、超时未消费或队列满了的情况下该消息就会成为死信消息。

我们就可以利用消息的超时机制实现延迟队列,我们可以这样做,先创建一个正常交换机和队列以及死信交换机和队列,发送消息时指定一个超时时间ttl,当消息超时该消息自动到死信交换机,死信交换机路由到死信队列中,最后只要消费这个死信队列中的消息即可

怎么样处理消息堆积问题?

1、增加消费者或者提升消费速度

1、搭建RabbitMQ集群,增加服务器

2、提升消费速度,配置消费者一次性获取消息的数量以及最大消费者数量,当消费者数量不足时会自动增加,直到最大

2、使用惰性队列增加RabbitMQ存储的消息数量

惰性队列接收到消息后直接存入磁盘而非内存,要消费时才拿出来,这样可以存储大量消息。

但也带来了问题,因为基于磁盘,所以受限于磁盘I/O,消息实时性会降低