一篇完整的RabbitMQ面试指南

3,801 阅读4分钟

__没有最好的 只有适合的

前言

RabbitMQ是MQ中的一个优秀代表,它凭借自己的可靠性、低延迟等特性在众多MQ实现中占有一席之地,也是面试中常问的MQ。

如何搭建RabbitMQ高可用模式?

RabbitMQ有三种模式:单机模式、普通集群模式、镜像集群模式
单机和普通集群都不能实现高可用!
单机模式不用赘述。
普通集群模式也不存在高可用性,该模式下虽然启动多个RabbitMQ实例,但每个queue仍然只会放到一个RabbitMQ实例中,如果消费者从B消费,但消费的是A的queue,那B需要从A拉取消息,如果A挂了就无法消费了。

RabbitMQ镜像集群模式

镜像模式包含一个master和多个slave,分布在不同的节点上。除了publish外所有动作都只会向master发送,master将命令执行的结果广播给slave,slave会准确地按照master执行命令的顺序进行执行,所以队列的消费操作都是在master上完成的,但消息都同步保存在所有节点上。
如果master挂了,生产者发送的消息还保存在其他的slave上,此时将一个slave提升为master就又可以消费消息了!

RabbitMQ如何保证不丢数据?

上篇文章讲了从三个方面来防范丢失数据:生产端、队列本身、消费端 👍

  • 生产端:开启事务(不推荐,太耗性能降低吞吐),推荐开启confirm模式,在生产者那里设置开启confirm模式之后,你每次写的消息都会分配一个唯一的id,写入了RabbitMQ后,RabbitMQ会给你回传一个ack消息,说明消息发送成功了。如果RabbitMQ没能处理这个消息,会返回一个nack消息,告诉你这个消息接收失败。
  • 队列本身:开启RabbitMQ的持久化,消息写入之后会持久化到磁盘,就算机器挂了,也能恢复。
  • 消费端:通过手动comfirm机制确认消息已经被正确消费了。

怎么设置RabbitMQ持久化?

  1. 创建queue的时候将其设置为持久化,这样就可以保证RabbitMQ持久化queue的元数据,但是它是不会持久化queue里的数据的。
  2. 发送消息的时候将消息的deliveryMode设置为2,将消息也设置为持久化。

RabbitMQ有哪些组件、分别有什么作用?

  • ConnectionFactory(连接管理器):应用程序与RabbitMQ之间建立连接的管理器。
  • Channel(信道):消息推送使用的通道, Channel是创建在“真实”TCP上的虚拟连接,AMQP命令都是通过Channel发送出去的,每个信道都会有一个唯一的ID,不论是发布消息,订阅队列或者接收消息都是通过Channel完成的。
  • Exchange(交换器):用于转发消息,生产者的消息会首先进入Exchange, Exchange根据消息的RoutingKey查询路由表(BindingKey表),把消息发送到合适的Queue中。

常用的Exchange有三种:

  1. fanout:如果交换器收到消息,将会广播到所有绑定的队列上。
  2. direct:如果RoutingKey完全匹配,消息就被投递到相应的队列。
  3. topic:可以使来自不同源头的消息能够到达同一个队列。只要RoutingKey匹配路由表(BindingKey表)就可以转发, 使用topic交换器时,还可以使用通配符进行匹配。
  • Queue(队列):用于存储生产者的消息。
  • RoutingKey(路由键):生产者的消息根据RoutingKey分配到不同的Queue中。
  • BindingKey(绑定键):用于建立Exchange与Queue的连接(绑定关系),Exchange会建立一个绑定信息的查询表,用于路由消息到不同的Queue中。
  • VHost:虚拟主机,严格来说它不是组件只是一个概念,一个broker( RabbitMQ实例)里可以设置多个vhost,用作不同用户的权限分离。

RabbitMQ为什么使用Channel而不直接使用TCP发送命令?

考虑到TCP创建和销毁是非常昂贵的开销,而且操作系统每秒能创建的TCP也是有限的,业务高峰期将创建大量的连接,严重浪费资源,而且可能会遇到系统瓶颈。
如果我们每个请求都使用一条TCP连接,既满足了性能的需要,又能确保每个连接的私密性,完美👍。

RabbitMQ如何实现延迟消息队列?

  1. 通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能。
  2. 使用RabbitMQ-delayed-message-exchange插件实现延迟功能。

RabbitMQ是push模式还是pull模式

RabbitMQ两种模式都支持,但是主要使用的还是push模式,通过channel.basicConsume(QUEUE_NAME, false, consumer)完成消息的消费,push模式为RabbitMQ主动推给消费者进行消费,主动避免了消息的积压。
pull模式可以使用channel.basicGet(QUEUE_NAME, false)来获取消息,主要用于批量拉取消息的时候使用。

回见!