[RabbitMQ] RabbitMQ常见面试题

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343

🏵️热门专栏:

🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482

🍕 Collection与数据结构 (93平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482

🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482

🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482

🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482

🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482

🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482

🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482

感谢点赞与关注~~~

目录

  • [1. MQ的作用以及应用场景](#1. MQ的作用以及应用场景)
  • [2. 了解过哪些MQ?他们有什么区别?](#2. 了解过哪些MQ?他们有什么区别?)
  • [3. 介绍一些RabbitMQ的核心概念以及工作流程](#3. 介绍一些RabbitMQ的核心概念以及工作流程)
  • [4. RabbitMQ如何保证消息的可靠性(最高频)](#4. RabbitMQ如何保证消息的可靠性(最高频))
  • [5. RabbitMQ如何保证消息的顺序性?](#5. RabbitMQ如何保证消息的顺序性?)
  • [6. 如何保证消息消费时候的幂等性](#6. 如何保证消息消费时候的幂等性)
  • [7. 介绍一下RabbitMQ的死信队列](#7. 介绍一下RabbitMQ的死信队列)
  • [8. 介绍一下RabbitMQ的延迟队列](#8. 介绍一下RabbitMQ的延迟队列)
  • [9. 介绍一下RabbitMQ的工作模式](#9. 介绍一下RabbitMQ的工作模式)
  • [10. 消息积压的问题,如何处理?](#10. 消息积压的问题,如何处理?)
  • [11. RabbitMQ是推模式还是拉模式(前面没有涉及到)](#11. RabbitMQ是推模式还是拉模式(前面没有涉及到))

1. MQ的作用以及应用场景

消息队列是一种应用程序之间通信的一种方法,他允许系统组件以异步的方式进行交互,在不同的应用场景之下可以展现出不同的作用,常见的应用场景如下:

  • 异步解耦: 在业务流程中,⼀些操作可能非常耗时,但并不需要即时返回结果.可以借助MQ把这些操作异步化.
  • 流量削峰: 在访问量剧增的时候,应用任然需要发挥作用,扛得住压力,如果一味地在硬件方面投入,无疑是巨大的浪费,所以我们就需要使用MQ来控制流量,将请求排队处理,使得一些关键组件不会因为突然增长的访问压力而崩溃.
  • 消息分发
    当多个系统需要对同一个数据的更新做出响应的时候,可以使用MQ进行消息分发.订阅队列消息的系统都会收到通知(监听消息队列的消费者).比如支付成功之后,支付系统可以直接向MQ发送信息,其他系统订阅该消息,它们会直接收到消息,无需轮询数据库.
  • 延迟通知
    需要在特定的时间之后发送通知的场景中,可以使用MQ的延迟消息功能,比如在电子商务平台中,如果用户在下单之后一定时间之内未支付,可以使用延迟队列在超时后自动取消订单.

2. 了解过哪些MQ?他们有什么区别?

目前业界有很多MQ的产品,例如RabbitMQ,RocketMQ,Kafka,ZeroMQ等.

简单介绍三种的区别:

  1. Kafka
    Kafka一开始的目的是用于日志收集和传输,追求高吞吐量,性能卓越.单机吞吐量达到10万级别,在日志领域比较成熟,功能较为简单,主要支持简单的MQ功能.
  2. RabbitMQ
    采用Erlang语言开发,MQ功能比较完备,且几乎支持所有的主流语言,开源提供的界面也非常友好,吞吐量达到万级,舍去活跃度较高,文档更新频繁.
  3. RocketMQ
    采用Java语言开发.在可用性以及稳定性等方面都非常出色,吞吐量达到十万级,但是支持的语言不多,产品较新,文档较少,社区活跃度一般.

3. 介绍一些RabbitMQ的核心概念以及工作流程

RabbitMQ是一个消息中间件,也是一个生产者消费者模型,负责接收,存储并转发消息:

  • producer: 生产者,向RabbitMQ发送消息.
  • Consumer: 消费者,从RabbitMQ接收消息.
  • Broker: RabbitMQ服务器.
  • Connection: 生产者客户端或者是消费者客户端与RabbitMQ服务器之间的网络连接.允许客户端与RabbitMQ之间通行.
  • Channel: 连接里的一个虚拟通道,发送或者是接收消息都是通过通道进行的.Channel和Connection组合起来有点像线程池的模式.
  • Exchange: 交换机.负责接搜生产者发送的消息,之后根据路由算法对消息进行路由.
  • Queue: 消息队列,存储消息直到他们被消费者消费.

工作流程如下:

  1. producer生产了一条信息.
  2. producer连接到RabbitMQBroker,建立一个Connection,并开通一个信道.
  3. producer声明一个交换机,用于把消息路由到指定的交换机中.声明队列,用于把消息存储到指定的队列中.这些信息会在消息的标签中声明.
  4. producer经过Channel,发送消息到RabbitMQBroker中.
  5. RabbitMQBroker接收消息,并按照消息的标签路由到对应的交换机中,交换机再次按照标签存储到对应的队列中.
  6. 出队列之后,消息会经过Channel到达消费者客户端中.

4. RabbitMQ如何保证消息的可靠性(最高频)

可以从以下几个方面来回答,一共三大机制:

  1. 发送放投递可靠性(发送方确认)
    如果消息在到达服务器之前就已经发生了丢失,这时候消息根本没有到达RabbitMQ,我们就要通过发送放确认来解决.
    RabbitMQ提供了两种方式来保证消息投递的可靠性:confirm模式和return模式.confirm模式通过设置RabbitTemplate的ConfirmCallback属性来实现,return模式通过设置ReturnCallback属性来实现.
  2. RabbitMQ可靠性(消息持久化)
    如果RabbitMQ由于某种异常情况以外退出或者崩溃,交换机,队列或者消息可能会发生丢失.这时候我们就需要对交换机,队列和消息都设置持久化.Spring中,对队列和交换机设置持久化的时候,我们一般是使用Builder的durable方法来完成,设置消息的持久化我们一般对消息中的DeliveryMode属性设置为持久化来实现.
  3. 消费者可靠性(消费者确认)
    如果消息到达了消费者,如果消息处理异常的情况下,这条消息就会被删除,此时就会造成消息的丢失.我们就可以使用RabbitMQ提供的消息确认机制.消息确认分为两种模式,一种是自动确认模式,一种是手动确认模式.要保证消息的可靠性,我们一般使用手动确认来解决.Spring中通过配置文件来修改确认机制.分为None,Auto,Manual三种,其中Auto可以设置最大重试次数.

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

消息顺序性保障分为: 局部顺序性保障和全局顺序性保障方案

局部顺序性通常指的是在单个队列内部保证消息的顺序.全局顺序性是指在多个队列或多个消费者之间保证消息的顺序.

保证顺序性的策略有以下的策略:

  1. 单队列单消费者
    最简单的方法是使用单个队列,并有单个消费者进行处理,同⼀个队列中的消息是先进先出的,这是RabbitMQ来帮助我们保证的.
  2. 分区消费
    单个消费者的吞吐太低了,当需要多个消费者以提高处理速度时,可以使用分区消费.把⼀个队列分割成多个分区,每个分区由一个消费者处理,以此来保持每个分区内消息的顺序性.(针对一个队列有多个消费者的场景)
    但是RabbitMQ本身并不支持单个队列的分区消费,需要业务逻辑实现,或者借助Spring-cloud-Stream来实现.
  3. 消息确认机制
    使用手动消息确认机制,消费者在处理完一条消息之后,显示地发送确认,这样RabbitMQ才会移除并继续发送下一条消息.
  4. 业务逻辑控制
    在某些情况下,即使消息乱序到达,也可以在业务逻辑层面实现顺序控制.比如通过在消息中嵌入序列号,并在消费时根据这些信息来处理.

6. 如何保证消息消费时候的幂等性

对于MQ而言,幂等性是指同一条消息多次消费,对系统的影响是相同的.

MQ消费者的幂等性的解决方法,一般有以下几种:

  1. 全局唯一ID

    为每条消息分配一个唯一标识符,比如UUID或者MQ消息中唯一的ID,但是一定要保证唯一性.

    消费者接收到消息之后,先用该ID判断该消息是否已经消费过,如果已经消费过,则放弃处理.

    如果没有消费过,消费者开始处理消息,业务处理成功之后,把唯一的ID保存起来(数据库或Redis等).

    可以使用Redis的原子性操作,比如使用Set操作,在后面加上nx命令(存在的时候不设置)来保证幂等性,将唯一的id设置在Redis中,如果返回1,则说明之前没有设置过,正常消费,如果返回的是0,说明之前这个id被保存过,即证明这条消息已经被消费过了,不再进行消费,自动抛弃.

  2. 业务逻辑判断

    在业务逻辑层面进行判断以处理幂等性.

    例如: 通过检查数据库中是否已经存在相关的数据记录,或者使用乐观锁机制来避免更新已经被其他的事务修改的数据,再或者在处理消息之前,先检查业务相关的状态,确保消息对应的操作尚未执行,然后才进行处理,具体根据业务场景来处理.

7. 介绍一下RabbitMQ的死信队列

死信简单理解就是因为种种原因,无法被消费的信息,就是死信.

有死信,就会有死信队列,当一个消息在一个队列中变为死信之后,它能被重新被发送到另一个交换机中,这个交换机就是DLX(Dead Letter Exchange),绑定DLX的队列,就被称为死信队列(DLQ,Dead Letter Queue).

消息变为死信一般是由于一下的几种情况:

  1. 消息被拒绝.(Basic.reject/Basic.nack),比如超过最大的重试次数.
  2. 消息过期,超过TTL设置的过期时间
  3. 队列达到最大长度

8. 介绍一下RabbitMQ的延迟队列

延迟队列就是在消息发送以后,并不想让消费者立刻拿到消息,而是等待特定的时间之后,消费者才可以拿到消息进行消费.

RabbitMQ本身并没有直接支持延迟队列的功能,但是可以通过TTL+死信队列的方式结合模拟出延迟队列的功能.也可以通过RabbitMQ官方提供的一个延迟的插件来实现延迟队列的功能.

常见的应用场景有:

订单在10min之内未支付自动取消.

用户在注册成功之后,3天之后发起调查问卷

用户发起退款,24小时之内商家未处理,则默认同意退款.

9. 介绍一下RabbitMQ的工作模式

  1. 简单模式:一个队列直接对应一个消费者和一个生产者.
  2. 工作队列:一个队列对应一个生产者和多个消费者.
  3. 广播模式:包含一个生产者,一个交换机,交换机绑定了多个队列,一个队列对应一个消费者.
  4. 路由模式:和广播模式类似,但是交换机会根据路由键把消息发送到指定的队列中.
  5. 通配符模式:是路由模式的一种扩展,交换机根据路由键的匹配规则将消息路由到不同的消息队列中.
  6. RPC模式:通过两个队列实现了一个消息回调的过程.有点类似与我们在网络中学习的"请求和响应",这个功能是MQ的额外功能.
  7. 发布确认模式: 是RabbitMQ提供的一种确保消息可靠发送到RabbitMQ服务器的机制.在这种模式之下,生产者可以等待RabbitMQ服务器确认,可以确保消息已经被服务器接收并处理,就是我们在前面提到的保证消息可靠性的发送方确认机制.

10. 消息积压的问题,如何处理?

消息积压指的是在消息队列中,等待处理的消息数量超过了消费者的处理能力,导致消息在队列中不断堆积的现象.

通常有以下的几种原因:

  1. 消息生产过快: 在高流量或者高负载的情况下,生产者以极高的速率发送消息,超过了消费者的处理能力.
  2. 消费者处理能力不足: 消费者处理消息的速度跟不上消息生产的速度,也会导致消息在队列中积压.
  3. 网络问题: 因为网络延迟或者不稳定,消费者无法及时接收或确认消息,最终导致消息积压.
  4. RabbitMQ服务器配置偏低
    解决方案如下:
  5. 提高消费者效率
    • 增加消费者实例数量,比如新增机器.
    • 优化业务逻辑,比如使用多线程并发处理业务.
    • 设置prefetchCount,当一个消费者处于繁忙阶段的时候,把消息转发到其他未阻塞的消费者.
    • 消息发生异常时,设置合适的重试策略,或者是转入到死信队列.
  6. 限制生产者速率
    • 流量控制: 在消息生产者中实现流量控制,根据消费者处理能力动态调整发送速率.
    • 限流: 使用限流工具,为消息发送速率设置一个上限.
    • 设置过期时间:,如果消息过期未消费,可以配置死信队列,以免消息丢失,并减少对主队列的压力.
  7. 资源与配置优化.比如升级RabbitMQ服务器硬件,调整RabbitMQ的配置参数.

11. RabbitMQ是推模式还是拉模式(前面没有涉及到)

RabbitMQ支持两种消息传递模式,推模式和拉模式.

推模式: 消息中间件主动将消息推送给消费者.

拉模式: 消费者主动从消息中间件拉取消息.
RabbitMQ主要是基于推模式工作的,他的设计核心是让消息队列中的消费者接收到由生产者发送的消息.使用Channel.basicConsume方法订阅队列,RabbitMQ就会把消息推送到订阅该队列的消费者,如果只想从队列中获取单条消息而不是持续订阅,则可以使用Channel,basicGet方法来进行消费消息.

相关推荐
用户83071968408238 分钟前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
用户8307196840822 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者3 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者5 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧6 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖6 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农6 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者6 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端
业精于勤_荒于稀6 天前
物流订单系统99.99%可用性全链路容灾体系落地操作手册
分布式
Ronin3056 天前
信道管理模块和异步线程模块
开发语言·c++·rabbitmq·异步线程·信道管理