90-面试题
RabbitMQ 如何保证可靠性?
这个一般不会这样问,它是一般会这样问:消息丢失了怎么办?MQ 可靠性怎么保证的?这样之类的话
Broker因此就要从这几个方面入手:
| 问题 | 解决措施 |
|---|---|
| 生产者到交换机 | 采用发布确认机制中的 confirm 模式 |
| 交换机到队列 | 采用发布确认机制中的 return 模式 |
| 队列到消费者 | 采用消息确认机制 |
Broker | 持久化 |
| 详细的内容去对应的章节里面查询,这里就不讲述了 |
请给我介绍一下什么是死信
相关的面试题还有:死信的应用场景,死信发生的条件等
死信是经常出现在这样的场景:
- 消息的
TTL过期 - 消息太多,超过了队列的最大长度
- 消息被消费了,但是是
NACK
死信可以配合 TTL 处理支付这样的业务场景
- 支付订单正常发出,设置了一个过期时间(TTL)
- 当用户超过了指定的过期时间还没有付款,那么就把它放入死信队列
- 处理死信队列的消费者就可以把订单的状况设置为“已取消”
还可以配合 NACK 来处理异常的工单:当出现消息多次异常消费的情况,就可以把消息放入死信队列,然后交给人工处理
请介绍一下什么是延迟队列
类似的问题:消息的延迟是如何实现的?
如果是标题这样的问题,那么答题顺序依然是
- 介绍一下概念
- 说一下实现方式
- 说一下应用场景
延迟队列是延迟处理消息的一类队列,相比于正常的队列,它最大的特点是不会及时处理消息,而是过了一段时间后再处理
在 RabbitMQ 中,它实现的方式有两种:
- 通过死信队列+TTL 的方式来处理,但是它有几个问题:
- 需要创建两个队列和交换机,增加了系统的复杂性
- 如果是针对消息的 TTL,那么在后传入的消息先过期的情况下,会导致延迟时间不准确
- 还可以通过插件的方式来处理,不过它需要配置,而且有一定的版本要求
像消息延期通知,订单一定时间内未支付而自动取消,用户注册过一段时间后的满意度调查,这些都是延迟队列的应用场景
RabbitMQ 如何保证幂等性呢?
MQ 中的幂等性是指相同的消息被多次消费,消耗的性能是相同的
它常见的传输策略有三个:
- 最多一次
- 至少一次
- 恰好一次(这个一般是没有实现的)
如果对精确性要求不高的业务(日常的不重要的日志),那么使用“最多一次”这个策略就可以,如果对精确性要求较高的业务(金融),那么就要采用“至少一次”这个策略了。
如果采用“至少一次”,那么就会出现消息重复这个问题,因此需要采用一些策略保障不重复处理
在 MQ 中,像 生产者到 MQ, MQ 到消费者 这两端区间内都可能会出现问题,比如网络波动,因此需要对此特殊处理
- 一个比较通用的方法就是设置唯一ID, 像 UUID, 用户 ID, 时间戳+UUID 等。
- 每一次判断后,对这个 ID 经行判断一下,判断它是否处理过业务
- 如果没有处理,那么就处理一下,然后把唯一ID保存起来
如何保障消息的顺序性呢?
首先这里的顺序性不是接收到消息的顺序性,而是处理消息的顺序性。因为 RabbitMQ 是不能保证接收的顺序,它也不清楚生产者生产的顺序。 网络波动、多生产者等都是会影响到这个顺序,而这些往往是不可控的。
在以下这些情况下,MQ 可能会出现顺序不一致的问题:
- 网络波动
- 多个消费者
- 消息重试
- 复杂的路由策略
而顺序性的保障也分为两种:
- 全局顺序性保障:所有队列中的消息先后顺序要一样
- 局部顺序性保障:只要保障当前队列中的消息先后的消费顺序一样即可
一般情况下,使用局部顺序性保障就可以满足大部分的业务需求,如果采用全局顺序性保障,效率会比较低。
为了保障局部顺序性,可以采用以下几个措施:
- 单队列单消费者
- 多个消费者分区消费(比如可以取模来分区)
- 消息确认,通过限制 Qos 来实现
- 还可以通过一系列业务逻辑来保障
消息积压了怎么办?
消息积压是指消费者消费消息的速度跟不上生产者生产的速度,导致队列中的消息越来越多的情况。
它出现的原因有很多,比如:
- 生产者生产速度过快
- 消费者处理过慢:
- 消费者服务器配置太低
- 消费者代码逻辑错误,导致消息一直没有被确认
- 消费者代码的性能过低
- 代码逻辑太复杂
- 网络问题导致消息一直没有被确认
针对这些问题,需要有针对性地处理问题,但是一般情况下,不会限制生产者的生产速度,主要处理的是消费者那一部分