Advertisement

【硬核干货】RabbitMQ面试题附答案

阅读量:

这里写目录标题

  • 什么是消息队列(Message Queue)?
  • 消息队列的主要优点有哪些?
  • 请解释解耦功能是什么?
  • 异步传输的特点是什么?
  • 请说明削峰(Sharding)的作用是什么?
  • 消息队列有哪些明显的缺点?
  • 什么是RabbitMQ?
  • 在什么场景下通常会使用RabbitMQ?
  • 请简述RabbitMQ的基本概念。
  • 在什么情况下保证消息顺序性显得尤为重要?为什么?
  • 消息是如何实现分发的?能否详细说明其机制?
  • 如何确保消息被正确发送并被消费?系统中可能出现什么问题?
  • 面对延迟问题应采取哪些措施?如果队列已满怎么办?当有几百万的消息长期滞留该怎么办?
  • 如何构建高可用性的系统?RabbitMQ集群是如何实现高可用性的?

1.什么是MQ

MQ就是消息队列。是软件和软件进行通信的中间件产品

MQ的优点

简答题
异步处理 - 与传统串行和并行方法相比,在提高系统吞吐量方面具有显著优势。
应用解耦 - 通过消息通信机制实现系统间的解耦设计,在不干预其他系统的情况下完成功能交互。
流量削锋 - 消息队列的长度能够有效控制请求流量,并在短时间内应对高并发的挑战。
日志处理 - 针对大量日志数据的高效传输需求,该方法提供了有效的解决方案。
消息通讯 - 采用高效的通信机制后,在支持传统点对点消息传递的同时还可以灵活应用于像聊天室这样的实时交互场景。

解耦、异步、削峰是什么?

模块独立化:A系统负责将数据传输至BCD三个子系统,并通过接口调用完成这一过程。若有其他系统如E也需要该数据怎么办?如果C系统当前不再需要相关功能,则A系统负责人对此感到非常困扰——因为A系统与其他众多杂乱无章的子系统之间存在严重的依赖关系。当A系统输出一条关键的数据信息时,在线的子系统都需要从其处获取数据支持。若采用消息队列技术,则A系统的操作变为:生成一个至关重要的数据信息并将其存入消息队列中;各子系统则需自行从消息队列中进行数据获取;若新子系统加入并需要获取该数据,则只需在其上发起消息消费请求即可;若某个子系统不再需要这条特定的数据信息,则可终止对该消息队列的消息监听请求——这样一来,A系统的维护工作就无需再考虑向何处发送数据的问题,也不用再关注对方是否成功接收、是否出现超时等异常情况了

采用异步机制:当A系统接收到一个请求时,不仅需要在其本地数据库中进行数据更新(耗时3ms),还需对B、C、D三个系统的本地数据库进行数据更新(分别耗时300ms、450ms和200ms)。因此该请求的总延迟时间为3ms(本地)加上B系统300ms、C系统450ms和D系统200ms的时间(总计953ms),接近1秒。由于用户的体验较差(慢死了慢死了),建议改用消息队列MQ技术。当用户通过浏览器发起请求时,在线程层面发送三条消息到MQ队列中(耗时5ms),而整个流程的时间开销仅为8ms(从接收请求到返回响应)。

削峰 :减少高峰时期对服务器压力。

消息队列有什么缺点

缺点有以下几个:

原本系统的运行状况良好;然而,在强制性地引入消息队列后(即非得加入),如果该消息队列出现故障,则会导致系统的可用性显著下降。

系统复杂度有所提升
引入消息队列后需综合考量多个方面的挑战。例如:数据一致性问题、防止消息被无端复制或误用以及保障数据传输的安全性和可靠性等技术难题都需要一一应对。进而导致系统设计变得更加复杂化和难度增加

  1. 一致性问题
    系统A完成处理后立即返回成功状态,在此情况下所有人都认为请求已经得到了成功的处理。然而,在BCD三个系统的场景下,请注意:在BCD三个系统的运行环境中需要特别关注的一点是,在BCD三个系统的运行过程中可能出现异常情况。具体来说,在BCD三个系统的运行过程中,请确保以下几点:首先,在BCD三个系统的运行过程中,请确保BD两个系统的写入操作均已完成;其次,在BCD三个系统的运行过程中,请确保C系统未能完成写入操作就会导致整个数据一致性问题的出现

什么是RabbitMQ?

RabbitMQ是一款开源软件(基于Erlang开发),消息中间件;其最大的特点是消费者无需依赖于提供者的存在,并实现了服务间高度解耦的能力。它支持解耦、异步操作以及削峰处理。

rabbitmq 的使用场景

(1)服务间异步通信
(2)顺序消费
(3)定时任务
(4)请求削峰

RabbitMQ基本概念

Broker: 可以理解为一个消息队列服务器实例
Exchange: 该组件主要负责按照指定规则将消息路由到相应的队列
Queue: 每个消息都会被投递至一个或多个独立队列
Binding: 通过绑定机制将exchange与queue按照预设路由进行连接
Routing Key: 该键决定了message如何被投递至目标队列
VHost: vhost 实际上是一个虚拟化的broker环境,在其中运行着独立的队列、交换机和绑定机制,并具备权限隔离功能
Producer: 负责向系统中发送message的任务程序
Consumer: 专门接收并处理message的对象程序
Channel: 在客户端连接中最多可创建多个通道来建立多个会话

如何保证RabbitMQ消息的顺序性?

将多个消息队列拆分成独立的消费者节点能够提升系统的扩展性;然而这种方式虽然增加了消息队列的数量(即每个消费节点是一个独立的消息处理实体),同时也带来了额外的复杂性(如管理更多的消费节点可能会增加系统资源消耗)。另一种做法是将单个消息队列分配给一个消费者节点,并通过该消费者节点内的逻辑实现复杂的业务流程;然后将该消费者内的所有操作进一步分配给底层不同的 worker 处理。

消息如何分发?

如果该队列中存在至少一名消费者订阅,则系统会将消息按轮转(round-robin)的方式依次发送给每个订阅的消费者。每条消息只会分配给一名订阅者(前提是该订阅者能够正常接收并确认信息)。路由机制支持多消费者的高效信息处理。

如何确保消息正确地发送至 RabbitMQ? 如何确保消息接收方消费了消息?

发送方确认模式
将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯
一的 ID。
一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认
给生产者(包含消息唯一 ID)。
如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(notacknowledged,未确
认)消息。
发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到
达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。
接收方确认机制
消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确
认了消息,RabbitMQ 才能安全地把消息从队列中删除。
这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消
息。也就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息。保证数
据的最终一致性;
下面罗列几种特殊情况
如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被分发,
然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重)
如果消费者接收到消息却没有确认消息,连接也未断开,则 RabbitMQ 认为该消费者繁忙,将不
会给该消费者分发更多的消息。

如何降低消息队列运行中的延迟并实现数据过期后自动清除的目标?当消息队列变得满员时该如何配置机制以避免溢出?面对几百万条消息长时间堆积在队列中该怎么办?

为应对消息系统中的积压问题,在短时间内提升资源 capacity

接着临时征用 10 倍规模的机器资源来运行这些 new consumers 程序

如何保证高可用的?RabbitMQ 的集群

RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的,我们就以 RabbitMQ
为例子讲解第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式:单机模式、普通集群模
式、镜像集群模式。
1. 单机模式 ,就是 Demo 级别的,一般就是你本地启动了玩玩儿的?,没人生产用单机模式
2. 普通集群模式:
意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。
你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据
(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。
你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉
取数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读
写操作。
3. 镜像集群模式
这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群
模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是
说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意
思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。
RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策
略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再
次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。
这样的好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue
的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能
开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ
一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的
完整数据。

全部评论 (0)

还没有任何评论哟~