10、RabbitMQ高频面试题

1、你们项目中哪里用到了RabbitMQ

RabbitMQ是我们项目中服务通信的主要方式之一 , 我们项目中服务通信主要有二种方式实现 :

  1. 通过Feign实现服务的同步调用
  2. 通过MQ实现服务的异步通信

下面要结合自己的项目中功能来说两个地方

  1. xxx

  2. xxx

2、为什么会选择使用RabbitMQ

我们项目中之所以选择使用RabbitMQ,是因为它的功能比较丰富 , 支持各种消息收发模式, 支持延迟队列 , 惰性队列

而且天然支持集群, 保证服务的高可用, 同时性能非常不错 , 社区也比较活跃, 文档资料非常丰富

使用MQ有很多好处,简单跟您说几个:

  • 吞吐量提升:无需等待订阅者处理完成,响应更快速

  • 故障隔离:服务没有直接调用,不存在级联失败问题

  • 调用间没有阻塞,不会造成无效的资源占用

  • 耦合度极低,每个服务都可以灵活插拔,可替换

  • 流量削峰:不管发布事件的流量波动多大,都由Broker接收,订阅者可以按照自己的速度去处理事件

当然使用使用MQ也有一些缺点

  • 架构复杂了,业务没有明显的流程线,不好管理
  • 需要依赖于Broker的可靠、安全、性能

总之,瑕不掩瑜,使用了RabbitMQ之后可以大大提供程序的效率

3、使用RabbitMQ如何保证消息不丢失

消息从生产者发送到消费者接收,会经历多个过程 , 其中的每一步都可能导致消息丢失

大体可以分为这样几种情况:

  1. 消息发送到交换机丢失
  2. 消息从交换机路由到队列丢失
  3. 消息保存到队列中丢失
  4. 消费者消费消息丢失

针对每一步,RabbitMQ分别给出了解决方案:

  1. 消息发送到交换机丢失:发布者确认机制

    消息发送到交换机失败会向生产者返回失败原因,生产者通过回调接收发送结果,如果发送失败,重新发送,或者记录日志人工介入

  2. 消息从交换机路由到队列丢失:发布者回执机制

    消息从交换机路由到队列失败会向生产者返回失败原因 ,生产者通过回调接收回调结果,如果发送失败,重新发送,或者记录日志人工介入

  3. 消息保存到队列中丢失:MQ持久化

    RabbitMQ运行开启交换机持久化、队列持久化、消息持久化,以保证消息在传输过程中不会丢失

  4. 消费者消费消息丢失:消费者确认机制

    消费者确认机制指的是只有消费者一方确认消息消费成功了,mq才删除消息,否则就会重新发送消息给消费者

通过RabbitMQ本身所提供的机制基本上已经可以保证消息不丢失, 但是因为一些特殊的原因还是会发送消息丢失问题 ,

例如 : 回调丢失 , 系统宕机, 磁盘损坏等 , 这种概率很小 , 但是如果想规避这些问题 , 进一步提高消息发送的成功率, 也可以通过程序自己进行控制

设计一个消息状态表 , 主要包含 : 消息id , 消息内容 , 交换机 , 消息路由key , 发送时间, 签收状态等字段 , 发送方业务执行完毕之后 , 向消息状态表保存一条消息记录, 消息状态为未签收 , 之后再向MQ发送消息 , 消费方接收消息消费完毕之后 , 向发送方发送一条签收消息 , 发送方接收到签收消息之后 , 修改消息状态表中的消息状态为已签收 ! 之后通过定时任务扫描消息状态表中这些未签收的消息 , 重新发送消息, 直到成功为止 , 对于已经完成消费的消息定时清理即可 !

4、消息的重复消费问题如何解决的

在使用RabbitMQ进行消息收发的时候,如果发送失败或者消费失败会自动进行重试,那么就有可能会导致消息的重复消费

解决方案:

  • 每条消息设置一个唯一的标识id
  • 幂等方案
    • token+redis
    • 分布式锁
    • 数据库锁(悲观锁、乐观锁)

5、如何解决消息堆积在MQ的问题

解决消息堆积有几种种思路:

  1. 提高消费者的消费能力,例如使用多线程消费
  2. 增加消费者数量,提高消费速度,可以使用ork队列模式,设置多个消费者消费消费同一个队列中的消息
  3. 扩大队列容积,提高堆积上限
  4. 使用RabbitMQ惰性队列,接收到消息后直接存入磁盘而非内存,消费者要消费消息时才会从磁盘中读取并加载到内存

6、RabbitMQ如何保证消费的顺序性

一个队列只设置一个消费者消费即可 , 多个消费者之间是无法保证消息消费顺序性的

7、RabbitMQ的延迟队列有了解过嘛

RabbitMQ的延迟队列有两种实现方案 :

  1. 使用消息过期TTL + 死信交换机
  2. 使用延迟交换机插件

8、RabbitMQ如何设置消息过期

RabbitMQ设置消息过期的方式有两种 :

  1. 在队列上设置过期时间,所有进到这个队列的消息就会具有统一的过期时间

  2. 为消息单独设置过期时间

注意 :

  1. 队列过期和消息过期同时存在 , 会以时间短的时间为准
  2. RabbitMQ队列消息过期的机制是判断队列头部元素是否过期 , 如果队里头部消息没有到过期时间 , 中间消息到了过期时间, 这个消息也不会被自动剔除

9、什么是死信交换机

死信交换机和正常的交换机没有什么不同,当一个包含死信的队列使用dead-letter-exchange属性,指定了一个交换机,这个交换机称为死信交换机

也就是说只有队列中的死信才会流转到死信交换机,而当一个队列中的消息满足下列情况之一时,就会成为死信:

  • 消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数设置为false
  • 消息是一个过期消息,超时无人消费
  • 要投递的队列消息满了,无法投递

一般的死信交换机还会再跟着一个专门的队列,用来专门存储所有的死信,以方便后期的人工干预

10、RabbitMQ的集群有哪些

RabbitMQ天然支持集群模式,它的集群有两种模式:

  • 普通集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力

    这种集群会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息。

    当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回

    如果队列所在节点宕机,队列中的消息就会丢失

  • 镜像集群:是一种主从集群,普通集群的基础上,添加了主从备份功能,提高集群的数据可用性。

    这种集群模式下,交换机、队列、队列中的消息会在各个mq的镜像节点之间同步备份

    创建队列的节点被称为该队列的主节点,备份到的其它节点叫做该队列的镜像节点。

    一个队列的主节点可能是另一个队列的镜像节点

    所有操作都是主节点完成,然后同步给镜像节点

    主宕机后,镜像节点会替代成新的主

相关推荐
用户8307196840821 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
Lee川1 天前
优雅进化的JavaScript:从ES6+新特性看现代前端开发范式
javascript·面试
Lee川1 天前
从异步迷雾到优雅流程:JavaScript异步编程与内存管理的现代化之旅
javascript·面试
晴殇i2 天前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
绝无仅有2 天前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
绝无仅有2 天前
Redis大Key问题排查与解决方案全解析
后端·面试·架构
AAA梅狸猫2 天前
Looper.loop() 循环机制
面试
AAA梅狸猫2 天前
Handler基本概念
面试
Wect2 天前
浏览器缓存机制
前端·面试·浏览器
掘金安东尼2 天前
Fun with TypeScript Generics:玩转 TS 泛型
前端·javascript·面试