【2024最新精简版】RabbitMQ面试篇

在这里插入图片描述

文章目录

    • Kafka和RabbitMQ什么区别
    • 惰性队列(Lazy Queues)是怎么实现的?
    • RabbitMQ工作模式有哪些 ?
    • 你们项目中哪里用到了RabbitMQ ?
    • 为什么会选择使用RabbitMQ ? 有什么好处 ?
    • 使用RabbitMQ如何保证消息不丢失 ?
    • 消息的重复消费问题如何解决的 ?
    • 如果有100万消息堆积在MQ , 如何解决 ?
    • RabbitMQ如何保证消费的顺序性 ?
    • RabbitMQ的延迟队列有了解过嘛 ?
    • RabbitMQ如何设置消息过期 ?
    • 什么情况下消息会成为死信 ?
    • 什么是死信交换机 ? 如何为队列绑定死信交换机 ?
    • RabbitMQ的高可用机制有了解过嘛 ?

更多相关内容可查看

Kafka和RabbitMQ什么区别

RabbitMQRocketMQKafka
公司/社区Rabbit阿里Apache
开发语言ErlangJavaScala&Java
协议支持AMQP,XMPP,SMTP,STOMP自定义协议自定义协议
可用性
单机吞吐量一般非常高
消息延迟微秒级毫秒级毫秒以内
消息可靠性一般
  1. 底层开发语言不同 : RabbitMQ底层采用Erlang语言开发 , Kafka是基于Java和Scala语言的
  2. 协议支持不一样 : RabbitMQ支持AMQP和SMTP通过插件还能支持MQTT等协议 , Kafka是自定义的协议
  3. Kafka的吞吐量比RabbitMQ更高 , 性能比RabbitMQ更好
  4. RabbitMQ功能非常丰富 , 支持各种消息模式, 支持延迟消息 , 支持惰性队列 , 镜像队列等 , 还能通过插件扩展功能
  5. RabbitMQ对于消息可靠性保证的机制比较多, 例如 : 生产者确认机制 , 消费者签收机制等
  6. RabbitMQ基于队列存储消息和消费消息 , Kafka基于主题分区存储消息和消费消息

你们公司为什么选择RabbitMQ ?
我们选择RabbitMQ主要基于一下考虑 :

  1. RabbitMQ从可用性, 吞吐量, 消息延迟, 消息可靠性方面来说比较均衡
  2. RabbitMQ中支持丰富的消息收发类型
    1. 点对点消息 : 简单队列模式/工作队列模式
    2. 发布订阅消息 : 广播模式/ 路由模式/ 主题模式
  3. RabbitMQ支持丰富丰富的插件扩展, 通过插件可以提供更加丰富的特性和功能
  4. RabbitMQ社区非常活跃, 有大量的文档和案例供开发者学习
  5. 我们团队中有其他小伙伴之前用过RabbitMQ , 我们现在使用RabbitMQ成本比较低, 也可以规避一些使用过程中的问题

惰性队列(Lazy Queues)是怎么实现的?

惰性队列是指一种特殊类型的队列,它的主要特点是在消息持久化到磁盘时,采用了一种懒加载(Lazy Loading)的方式。当消息被发送到惰性队列时,并不立即将消息写入磁盘,而是先将消息缓存在内存中,然后根据一定的条件(如内存使用情况)将消息异步地写入磁盘。这样可以提高性能

RabbitMQ工作模式有哪些 ?

Rabbitmq的工作模式有六种:

  1. simple简单模式

image.png
生产者直接发送消息给RabbitMQ队列,消费者从队列消费。未定义和指定Exchange的情况下,使用的是内置的AMQP default这个Exchange

  1. work工作模式

image.png
生产者发送消息到队列中,多个消费者消费同一个队列的数据,可以达到负载均衡的效. 消费者之间对于同一个消息的关系是竞争的关系。
对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。例如:短信服务部署多个,只需要有一个节点成功发送即可

  1. publish/subscribe订阅模式

image.png
发布订阅模式主要是使用fanout类型交换器,routingKey忽略。每个消费者定义生成一个队列并绑定到同一个Exchange,每个消费者都可以消费到完整的消息。消息广播给所有订阅该消息的消费者。

  1. routing路由模式

image.png
路由模式主要使用direct类型的Exchange,发N条消费并使用不同的routingKey,消费者定义队列并将队列、routingKey、Exchange绑定。使用direct模式Exchagne必须要routingKey完全匹配的情况下消息才会转发到对应的队列中被消费

  1. topic 通配符模式

image.png
Topics 通配符模式主要是使用topic类型的交换器,队列绑定到交换器、bindingKey时使用通配符,交换器将消息路由转发到具体队列时会根据消息routingKey模糊匹配,比较灵活
topic类型的交换器背后原理跟direct类型的类似:只要队列的bindingKey的值与消息的routingKey匹配,队列就可以收到该消息。
通配符规则:#匹配一个或多个词,*匹配不多不少恰好1个词

  1. RPC模式

RPC即客户端远程调用服务端的方法 ,使用MQ可以实现RPC的异步调用,基于Direct交换机实现,流程如下:
1、客户端即是生产者也是消费者,向RPC请求队列发送RPC调用消息,同时监听RPC响应队列。
2、服务端监听RPC请求队列的消息,收到消息后执行服务端的方法,得到方法返回的结果。
3、服务端将RPC方法 的结果发送到RPC响应队列。
4、客户端(RPC调用方)监听RPC响应队列,接收到RPC调用结果。

你们项目中哪里用到了RabbitMQ ?

订单处理: 当用户提交采购订单时,ERP 系统可以将订单信息发布到 RabbitMQ 的消息队列中。然后,采购模块的消费者从消息队列中获取订单信息,进行处理,如验证订单、生成采购单等。
库存更新: 在采购订单被处理后,采购模块需要更新库存信息。ERP 系统可以将库存更新的消息发布到 RabbitMQ 中,由库存管理模块的消费者接收并更新库存数据。
RabbitMQ通过异步的方式来读取大数据量的数据

为什么会选择使用RabbitMQ ? 有什么好处 ?

选择使用RabbitMQ是因为RabbitMQ的功能比较丰富 , 支持各种消息收发模式(简单队列模式, 工作队列模式 , 路由模式 , 直接模式 , 主题模式等) , 支持延迟队列 , 惰性队列而且天然支持集群, 保证服务的高可用, 同时性能非常不错 , 社区也比较活跃, 文档资料非常丰富
使用MQ有很多好处:

  • 吞吐量提升:无需等待消费者处理完成,响应更快速
  • 故障隔离:服务没有直接调用,不存在级联失败问题
  • 调用间没有阻塞,不会造成无效的资源占用
  • 耦合度极低,每个服务都可以灵活插拔,可替换
  • 流量削峰:不管发布事件的流量波动多大,都由Broker接收,订阅者可以按照自己的速度去处理事件

使用MQ也有很多缺点:

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

因为我们公司中之前有其他小伙伴/之前有用过RabbitMQ作为消息中间件, 有一定的技术储备, 所以我们会选择使用RabbitMQ作为消息中间件, 这样学习成本和使用成本都很低, 而且能够避免在使用过程中的一些问题

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

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

针对这些问题,RabbitMQ分别给出了解决方案:

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

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

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

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

  1. 消息保存到队列中丢失 : MQ持久化(交换机持久化, 队列持久化 , 消息持久化)

  2. 消费者消费消息丢失 : 消费者确认机制 , 消费者失败重试机制

通过RabbitMQ本身所提供的机制基本上已经可以保证消息不丢失 , 但是因为一些特殊的原因还是会发送消息丢失问题 , 例如 : 回调丢失 , 系统宕机, 磁盘损坏等 , 这种概率很小 , 但是如果想规避这些问题 , 进一步提高消息发送的成功率, 也可以通过程序自己进行控制

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

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

  1. 消息去重表: 维护一个消息去重表,记录已经处理过的消息的唯一标识符。当消费者接收到消息时,首先检查该消息的唯一标识符是否已经存在于消息去重表中,如果存在则认为该消息已经被处理过,直接丢弃;如果不存在,则进行消息处理,并将该消息的唯一标识符记录到消息去重表中。
  2. 消息确认机制: 在消费者成功处理完消息后,向消息队列发送确认消息。消息队列收到确认消息后将该消息标记为已消费,下次不会再次发送给该消费者。RabbitMQ 中使用的是 AMQP 协议,其中包含了消息确认机制。

如果有100万消息堆积在MQ , 如何解决 ?

解决消息堆积有二种思路:
思路一 : 提高消费者的消费能力 , 可以开启多线程消费 , 条件允许的情况下可以增加消费者的数量 , 提高消费速度
思路二:扩大队列容积,提高堆积上限 , 将来不及消费的消息保存在磁盘上 , 高峰期过了之后慢慢消费 , 可以使用RabbitMQ惰性队列

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

所谓顺序消费,即保证消息的发送顺序要与消息的消费顺序保持一致 , RabbitMQ消息发送到队列中 , 队列本身就是有序的 , 所以RabbitMQ保证消费的顺序性 , 只用考虑消费者即可 , 出现消息乱序的场景主要有二种情况 :

  1. 一个queue,有多个consumer去消费,这样就会造成顺序的错误,consumer从MQ里面读取数据是有序的,但是每个consumer的执行时间是不固定的,无法保证先读到消息的consumer一定先完成操作,这样就会出现消息并没有按照顺序执行
  2. 一个queue对应一个consumer,但是consumer里面进行了多线程消费,这样也会造成消息消费顺序错误。

解决方案 :

  1. 队列与消费者一对一 , 一个队列设置一个消费者

将原来的一个queue拆分成多个queue,需要保证顺序性的一批消息发送到同一个队列 , 然后保证每个queue对应一个consumer

  1. 使用内存队列 , 一个queue只对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理

消费者不消费数据, 而是将需要保证顺序性的一批次消息保存到内存队列 , 开启工作线程从队列中获取消息消费

RabbitMQ的延迟队列有了解过嘛 ?

RabbitMQ的延迟队列有二种实现方案 :
一种常见的实现延迟队列的方式是使用 RabbitMQ 插件:RabbitMQ Delayed Message Plugin。该插件允许你在消息发送时指定延迟时间,消息将在指定的延迟时间之后才会被投递到队列中。安装和配置该插件后,你可以通过设置消息的 TTL(Time-To-Live)和消息的特定属性来实现延迟队列的功能。
另一种方式是自定义实现延迟队列,主要思路是使用两个队列:一个用于存放需要延迟处理的消息,另一个用于存放已经到达延迟时间的消息。当消息到达延迟时间后,将其从延迟队列移动到实际的队列中进行消费。这种方式需要在消息生产者和消费者中实现额外的逻辑来管理延迟消息的处理。

RabbitMQ如何设置消息过期 ?

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

  1. 为队列设置过期时间, 所有进到这个队列的消息就会具有统一的过期时间
@Bean
public Queue ttlQueue(){return QueueBuilder.durable("ttl.queue") // 指定队列名称,并持久化.ttl(10000) // 设置队列的超时时间,10秒.deadLetterExchange("dl.ttl.direct") // 指定死信交换机.build();
}
  1. 为消息单独设置过期时间
@Test
public void testTTLQueue() {// 创建消息String message = "hello, ttl queue";// 消息ID,需要封装到CorrelationData中CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());// 发送消息rabbitTemplate.convertAndSend("ttl.direct", "ttl", message, correlationData);// 记录日志log.debug("发送消息成功");
}

注意 :

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

什么情况下消息会成为死信 ?

当一个队列中的消息满足下列情况之一时,就会成为死信(dead letter):

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

什么是死信交换机 ? 如何为队列绑定死信交换机 ?

死 信交换机和正常的交换机没有什么不同 , 如果一个包含死信的队列配置了dead-letter-exchange属性,指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机称为死信交换机
为队列绑定死信交换机 , 只需要设置队列属性 dead-letter-exchange即可

RabbitMQ的高可用机制有了解过嘛 ?

RabbitMQ的是基于Erlang语言编写,而Erlang又是一个面向并发的语言,天然支持集群模式。RabbitMQ的集群有两种模式:
普通集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力。

  • 会在集群的各个节点间共享部分数据,包括:交换机、队列元信息。不包含队列中的消息。
  • 当访问集群某节点时,如果队列不在该节点,会从数据所在节点传递到当前节点并返回
  • 队列所在节点宕机,队列中的消息就会丢失

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

  • 交换机、队列、队列中的消息会在各个MQ的镜像节点之间同步备份。
  • 所有操作都是主节点完成,然后同步给镜像节点
  • 主宕机后,镜像节点会替代成新的主

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/29137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity中使用UI组件实现场景切换——6.18山大软院项目实训

设置场景切换 在Unity项目中,首先需要准备几个场景,并在项目的“Build Settings”中添加这些场景,以确保SceneManager可以加载它们。本例中,我们假设已有几个场景编号依次为1到5。 脚本概述 我们创建了一个SwitchScene类&#…

在IDEA 2024.1.3 (Community Edition)中创建Maven项目

本篇博客承继自博客Windows系统Maven下载安装-CSDN博客 Maven版本:maven-3.9.5 修改设置: 首先先对Idea的Maven依赖进行设置;打开Idea,选择“Costomize”,选择最下边的"All settings" 之后找到Maven选项&…

利用LabVIEW项目管理和组织LabVIEW应用程序

如何利用LabVIEW项目管理和组织LabVIEW应用程序,提供了关于文件定义、磁盘上的文件组织、LabVIEW项目浏览器、交叉链接和相关资源的建议。这些推荐在开发前就应建立,以确保应用程序能扩展到大量VIs并适应多开发者环境。 目录 定义和识别应用程序文件 磁…

黑龙江等保测评与企业安全:携手共筑数字时代坚固防线

在数字化转型的浪潮中,黑龙江的企业正以前所未有的速度拥抱新技术,推动业务创新与增长。然而,随着信息技术的深入应用,网络安全风险也随之增加,尤其是对个人信息与敏感数据的保护成为企业不容忽视的重大课题。信息安全…

【运维项目经历|032】Hadoop大数据处理与分析平台构建项目

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 🏅阿里云开发者社区专家博主 💊交流社区:CSDN云计算交流社区欢迎您的加入! 目…

List, Set, Map, Queue介绍

Java集合框架是一组接口和实现这些接口的类的集合,它提供了对数据集合的高效率存储和操作。以下是Java集合框架中一些核心接口的介绍: 1.List: List是一个有序的集合,允许包含重复的元素。它提供了按插入顺序访问元素的方法&…

leetcode56 合并区间

题目 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例 输入:intervals [[1,3],[2,6]…

6、 垃圾回收 浏览器事件循环

垃圾回收 & 浏览器事件循环 垃圾回收引用计数算法标记清除(mark-sweep)算法标记整理(Mark-Compact)算法 内存管理浏览器事件循环宏任务微任务整体流程 垃圾回收 垃圾回收,又称为:GC(garbag…

华火新能源集成灶评测:创新与品质的融合

在厨房电器的不断推陈出新中,华火新能源集成灶以其独特的魅力进入了人们的视野。今天,我们就来深入评测这款备受关注的产品——华火新能源集成灶 一、华火新能源集成灶的创新与环保 首先,我们先来探讨新能源集成灶的整体表现。华火新能源集成…

【面试干货】Hashtable 与 HashMap 的区别

【面试干货】Hashtable 与 HashMap 的区别 1、线程安全性2、对null值的处理3、遍历方式4、遍历示例5、总结 💖The Begin💖点点关注,收藏不迷路💖 在Java中,Hashtable和HashMap都是基于哈希表实现的Map接口。然而&#…

ERP、CRM、SRM、PLM、HRM、OA……都是啥意思?

经常会听说一些奇怪的系统或平台名称,例如ERP、CRM、SRM、PLM、HRM、OA等。 这些系统,都是干啥用的? █ ERP(企业资源计划) 英文全称:Enterprise Resource Planning 定义:由美国Gartner Gro…

网络安全复习笔记

概述 要素 CIA:可用性;完整性;保密性。 可控性;不可否认性;可审查性。 攻击 被动:窃听 - 保密性;监听 - 保密性主动:假冒 - 完整性;重放 - 完整性;改写 -…

11、Spring之Bean生命周期~依赖注入(2)

11、Spring之Bean生命周期~依赖注入(2) 依赖注入查找注入点对注入点进行赋值InjectionMetadata.inject()方法AutowiredFieldElement.inject()方法resolveFieldValue()方法resolveDependency方法createOptionalDependency()方法doResolveDependency()方法…

Java 面试题:Java 的文件拷贝方式有几种?哪一种最高效?

在Java编程中,文件操作是常见且重要的任务之一,其中文件拷贝(File Copy)是一种基本操作。Java提供了多种方式来实现文件拷贝,每种方式在性能、易用性和灵活性上各有优劣。了解并选择最适合的文件拷贝方法,对…

SQL Server数据库安装

原文:https://blog.c12th.cn/archives/26.html SQL Server数据库安装 测试:笔记本原装操作系统:Windows 10 家庭中文版 资源分享链接:提取码:qbt2 注意事项: 请严格按照步骤安装,SQL软件安装较…

el-table

el-table实现滚动效果 表格数据是websocket通信获取的数据,首次获取20条数据,以后新增订阅获取一条,新增一条则向上滑动显示最新数据。 const scroll (tableBody: any) > {// 先清除后设置cancelAnimationFrame(scrollTimer.value);let…

Matlab初识:什么是Matlab?它的历史、发展和应用领域

目录 一、什么是Matlab? 二、Matlab的历史与发展 三、Matlab的应用领域 四、安装和启动Matlab 五、界面介绍 六、第一个Matlab程序 七、总结 一、什么是Matlab? Matlab 是由 MathWorks 公司开发的一款用于数值计算、可视化以及编程的高级技术计算…

mysql 查询某表数据,更新另外一个表字段

1.根据子查询更新表字段(简单推荐) UPDATE demo d set d.user_name (select user_name from user u where u.user_code d.user_code) where d.user_name IS NULL2.使用join关联查询再插入 不想写了,累了有空再补 3.首先查询user表,找出与demo表中相…

spi service实现类加载代码

private static List<Factory> discoverFactories(ClassLoader classLoader) {//spi机制加载类final Iterator<Factory> serviceLoaderIterator ServiceLoader.load(Factory.class, classLoader).iterator();final List<Factory> loadResults new ArrayList…

第二证券今日投资参考:苹果WWDC大会开幕 地产板块再迎催化

上星期五&#xff0c;沪指盘中窄幅震动&#xff0c;创业板指在宁德年代的拖累下大幅下探。到收盘&#xff0c;沪指微涨0.08%报3051.28点&#xff0c;深证成指跌0.9%报9255.68点&#xff0c;创业板指跌2.16%报1781.07点&#xff0c;北证50指数涨0.93%&#xff0c;万得微盘股指数…