RabbitMQ面试题汇总

1 为什么要使用MQ?MQ和Redis模拟消息队列相比有什么优点?

为什么要使用MQ

  1. 解耦,系统与系统之间的耦合。
  2. 异步,非必要的业务逻辑可以以异步方式运行,加快响应速度
  3. 消峰,减少并发

对比Redis消息队列

  1. 消息消费的可靠性
    Redis没有相应的机制保证消息的消费,当消费者消费失败的时候,消息体丢失,需要手动处理, 例如用数据库、File等进行存储,以保证队列可以重新处理;

MQ一般都有消费确认机制,即使消费失败,也会自动使得消息体返回原队列,同时可全程持久化,保证消息体被正确消费;

  1. 发布的可靠性
    Redis不提供发布确认,需要自行实现,而MQ通常都有发布确认功能,保证消息被发布到服务器;

  2. 高可用
    Redis故障转移方案不够完美,而MQ集群通常采用磁盘、内存节点,任意单带那故障都不会影响整个队列的操作;

  3. 持久化
    Redis是数据持久化到磁盘,并不是单独针对消息队列。MQ通常队列、消息都可以单独选择是否持久化到磁盘。

  4. 消费者负载均衡
    Redis不提供,需要自行实现,MQ通常根据消费者情况,进行消息的均衡分发;

  5. 队列监控
    Redis不提供,需要自行实现,,Q可以兼容某个队列的所有信息(内存、磁盘、消费者、生产者、速率等)。

  6. 流量控制
    不提供,需要自行实现,MQ通常早服务器过载的情况下,对生产者速率进行限制,保证服务可靠性

  7. 出入对性能
    高并发下,MQ的入队性能通常高于Redis。

2 RabbitMQ中Broker指什么,cluster又是指什么?

broker是指一个或多个erlong node的逻辑分组,且node导航运行着rabbitma的应用程序。

cluster是再broker基础之上,增加node之间共享元数据的约束;

3 RabbitMQ的消息基于什么传输?

由于TCP连接的创建和小会开销较大,且并发数受系统资源限制,会造成性能瓶颈,RabbitMQ使用信道的方式来传输数据。信道是建立在真实的TCP内的虚拟连接,且每条TCP连接上的信道数量没有限制;

4 RabbitMQ的消息时如何分发的?

如果队列至少有一个消费者订阅,消息将以循环的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认);

5 消息怎么路由?

消息理由有三部分:交换器、路由、绑定。生产者把消息发布到交换器上,绑定决定了消息如何从路由器器路由到特定的队列;消息最终到达队列,并被消费者接收;

消息发布到交换器时,消息将用于一个路由键,在消息创建时设定。

通过队列路由键,可以把队列绑定到交换器上。

消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配,如果能够匹配到队列,则消息会投递到相应的队列中; 如果不能匹配到任何队列,消息将进入黑洞。

常用交换器有三种:

  • direct:如果路由键完全匹配,消息就诶投递到相应的队列;
  • fanout: 如果交换器收到消息,将会广播到所有绑定的队列上;
  • topic 可以使来自不同源头的消息能够匹配到达同一个队列。

6 如何确保消息正确地发送至RabbitMQ

Rabiitmq使用发送确认模式,确保消息正确地发送到RabbitMQ.
发送确认模式:将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一ID。一旦消息被投递到目的队列后,或者消息被写入磁盘后,信道会发送一个确认给生产者(包含消息唯一ID)。如果RabbitMQ内部错误从而导致消息丢失,会发送一跳未确认消息。发送方确认模式是异步的,生产者应用程序在等待确认的同事,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被处罚来处理确认消息。

7 如何保证消息接收方消费了消息?

消费者接受每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全第把消息从队列中删除。这里并没用用到超时机制,RabbitMQ仅通过Consumer的链接中断来确认会否需要重新发送消息。也就是说,只要链接不中断,Rabbitmq给了Consumer足够长的时间来处理消息。

特殊情况:

  • 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ会认为消息没有被分发,然后重新分发给下一个订阅的消费者;
  • 吐过消费者接收到消息却没有确认消息,连接也未断开,则RabbitMQ认为该消费者繁忙,将不会给消费者分发更多的消息;

8 如何避免消息重复投递或重复消费?

在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,做为去重和幂等的依据,避免重复的消息进入队列。在消息消费时,要求消息体重必须要有一个bizId做为去重和幂等的依据,避免同一消息被重复消费。

9 如何解决丢数据的问题?

生产者丢数据
开启transaction和confirm模式来保证生产者不丢消息。

transaction类似于数据库事务,发送过程中发送异常事务就会回滚。

confirm是确认机制,投递成功则发一条ACK给生产者,投递失败则发一条NACK给生产者,以便重试。

如果是rabbitmq断连,程序员异常,则需要进行异常处理,进行本地端记录,但由于无法保证全部异常都处理, 也可以将投递的消息全部存于本地后,投递成功则标记。

消息队列丢数据
开启持久化磁盘配置,配合comfirm机制,rabbitmq在持久话后,才会给生产者发送ACK。

消费者丢数据
启用手动确认模式

发表评论

邮箱地址不会被公开。 必填项已用*标注