Skip to content

90-面试题 ​

RabbitMQ 如何保证可靠性? ​

这个一般不会这样问,它是一般会这样问:消息丢失了怎么办?MQ 可靠性怎么保证的?这样之类的话

RabbitMQ如何保证可靠性
RabbitMQ如何保证可靠性
它可能在这几个地方出现问题:生产者到交换机,交换机到队列,队列到消费者和 Broker

因此就要从这几个方面入手:

问题解决措施
生产者到交换机采用发布确认机制中的 confirm 模式
交换机到队列采用发布确认机制中的 return 模式
队列到消费者采用消息确认机制
Broker持久化
详细的内容去对应的章节里面查询,这里就不讲述了

请给我介绍一下什么是死信 ​

相关的面试题还有:死信的应用场景,死信发生的条件等

02-RabbitMQ高级特性-死信
02-RabbitMQ高级特性-死信
死信是由于种种原因,导致一些消息始终没有被消费掉,这些消息就是死信

死信是经常出现在这样的场景:

  • 消息的 TTL 过期
  • 消息太多,超过了队列的最大长度
  • 消息被消费了,但是是 NACK

死信可以配合 TTL 处理支付这样的业务场景

  1. 支付订单正常发出,设置了一个过期时间(TTL)
  2. 当用户超过了指定的过期时间还没有付款,那么就把它放入死信队列
  3. 处理死信队列的消费者就可以把订单的状况设置为“已取消”

还可以配合 NACK 来处理异常的工单:当出现消息多次异常消费的情况,就可以把消息放入死信队列,然后交给人工处理

请介绍一下什么是延迟队列 ​

类似的问题:消息的延迟是如何实现的?

如果是标题这样的问题,那么答题顺序依然是

  1. 介绍一下概念
  2. 说一下实现方式
  3. 说一下应用场景

延迟队列是延迟处理消息的一类队列,相比于正常的队列,它最大的特点是不会及时处理消息,而是过了一段时间后再处理

在 RabbitMQ 中,它实现的方式有两种:

  1. 通过死信队列+TTL 的方式来处理,但是它有几个问题:
    1. 需要创建两个队列和交换机,增加了系统的复杂性
    2. 如果是针对消息的 TTL,那么在后传入的消息先过期的情况下,会导致延迟时间不准确
  2. 还可以通过插件的方式来处理,不过它需要配置,而且有一定的版本要求

像消息延期通知,订单一定时间内未支付而自动取消,用户注册过一段时间后的满意度调查,这些都是延迟队列的应用场景

RabbitMQ 如何保证幂等性呢? ​

MQ 中的幂等性是指相同的消息被多次消费,消耗的性能是相同的

它常见的传输策略有三个:

  1. 最多一次
  2. 至少一次
  3. 恰好一次(这个一般是没有实现的)

如果对精确性要求不高的业务(日常的不重要的日志),那么使用“最多一次”这个策略就可以,如果对精确性要求较高的业务(金融),那么就要采用“至少一次”这个策略了。

如果采用“至少一次”,那么就会出现消息重复这个问题,因此需要采用一些策略保障不重复处理

在 MQ 中,像 生产者到 MQ, MQ 到消费者 这两端区间内都可能会出现问题,比如网络波动,因此需要对此特殊处理

  • 一个比较通用的方法就是设置唯一ID, 像 UUID, 用户 ID, 时间戳+UUID 等。
  • 每一次判断后,对这个 ID 经行判断一下,判断它是否处理过业务
  • 如果没有处理,那么就处理一下,然后把唯一ID保存起来

如何保障消息的顺序性呢? ​

首先这里的顺序性不是接收到消息的顺序性,而是处理消息的顺序性。因为 RabbitMQ 是不能保证接收的顺序,它也不清楚生产者生产的顺序。 网络波动、多生产者等都是会影响到这个顺序,而这些往往是不可控的。

在以下这些情况下,MQ 可能会出现顺序不一致的问题:

  • 网络波动
  • 多个消费者
  • 消息重试
  • 复杂的路由策略

而顺序性的保障也分为两种:

  • 全局顺序性保障:所有队列中的消息先后顺序要一样
  • 局部顺序性保障:只要保障当前队列中的消息先后的消费顺序一样即可

一般情况下,使用局部顺序性保障就可以满足大部分的业务需求,如果采用全局顺序性保障,效率会比较低。

为了保障局部顺序性,可以采用以下几个措施:

  1. 单队列单消费者
  2. 多个消费者分区消费(比如可以取模来分区)
  3. 消息确认,通过限制 Qos 来实现
  4. 还可以通过一系列业务逻辑来保障

消息积压了怎么办? ​

消息积压是指消费者消费消息的速度跟不上生产者生产的速度,导致队列中的消息越来越多的情况。

它出现的原因有很多,比如:

  1. 生产者生产速度过快
  2. 消费者处理过慢:
    1. 消费者服务器配置太低
    2. 消费者代码逻辑错误,导致消息一直没有被确认
    3. 消费者代码的性能过低
    4. 代码逻辑太复杂
  3. 网络问题导致消息一直没有被确认

针对这些问题,需要有针对性地处理问题,但是一般情况下,不会限制生产者的生产速度,主要处理的是消费者那一部分