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

news2024/11/25 12:34:36

在这里插入图片描述

文章目录

    • 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.coloradmin.cn/o/1834076.html

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

相关文章

3.1、前端异步编程(超详细手写实现Promise;实现all、race、allSettled、any;async/await的使用)

前端异步编程规范 Promise介绍手写Promise(resolve,reject)手写Promise(then)Promise相关 API实现allraceallSettledany async/await和Promise的关系async/await的使用 Promise介绍 Promise是一个类,可以翻…

Spring技术——介绍、初识

从这篇博客正式开始学习 Spring 。 一、整个Spring技术学习的介绍 首先先对 Spring 做一个简单的认识,并从以下3个方面了解学习Spring 技术的意义: (1)为什么要学习 Spring 技术? 1、它的市场的占有率很高&#xff…

webpack 压缩图片

压缩前: 压缩后: 压缩后基本上是压缩了70-80%左右 1.依赖版本及配置 "imagemin-webpack-plugin": "^2.4.2", "imagemin-mozjpeg": "^7.0.0", "imagemin-pngquant": "^5.0.1", "webpa…

ClickHouse安装与下载22.3.2.2

ClickHouse安装与下载 目录 1. ClickHouse简介 1.1 ClickHouse优点: 1.2 ClickHouse缺点: 1.3 ClickHouse引擎: 1.3.1 数据库引擎 1.3.2 表引擎 2. ClickHouse下载安装 2.1 ClickHouse下载安装 2.2 ClickHouse使用 1. ClickHouse简…

五要素便携式气象站

TH-BQX5自然灾害,如暴雨、洪水、飓风等,对于人类生活的影响和威胁始终不可忽视。在应对自然灾害的过程中,提高应急响应和预警能力成为了一项迫切而重要的任务。近年来,五要素便携式气象站因其便捷、精准的特点,在自然灾…

大数据技术与实践学习

大数据技术与实践期末复习 生态系统 每一张图片都值得思考,理清楚到底是什么! 1.结构化数据(数据库里面的):Sqoop(效率比较慢/隔一段时间抽取一次) 2.半结构化或者非结构化数据:F…

Coursera耶鲁大学金融课程:Financial Markets 笔记Week 02

Financial Markets 本文是学习 https://www.coursera.org/learn/financial-markets-global这门课的学习笔记 这门课的老师是耶鲁大学的Robert Shiller https://en.wikipedia.org/wiki/Robert_J._Shiller Robert James Shiller (born March 29, 1946)[4] is an American econom…

细说MCU通过定时器输出PWM波形的实现方法

目录 一、硬件及工程 二、建立工程 三、代码修改 1、重定义回调函数 2、启动定时器中断 四、下载运行 一、硬件及工程 文章依赖的硬件及工程配置参考本文作者的其他文章:细说ARM MCU的串口接收数据的实现过程-CSDN博客 细说ARM MCU的串口接收数据的实现过程-C…

Matlab基础语法:变量和数据类型,基本运算,矩阵和向量,常用函数,脚本文件

目录 一、变量和数据类型 二、基本运算 三、矩阵和向量 四、常用函数 五、脚本文件 六、总结 一、变量和数据类型 Matlab 支持多种数据类型,包括数值类型、字符类型和逻辑类型。掌握这些基本的变量和数据类型,是我们进行数学建模和计算的基础。 数…

IT入门知识第三部分《软件开发》(3/10)

目录 IT入门知识大纲第三部分《软件开发》 1. 软件开发生命周期(SDLC) 1.1 需求分析 1.2 软件设计 1.3 程序编码 1.4 软件测试 1.5 项目部署 1.6 运行维护 2. 软件开发方法论 2.1 瀑布模型 2.2 敏捷开发 2.2.1 Scrum 2.2.2 Kanban 2.3 Dev…

ip地址b类和c类的区别是什么?体现在哪里

在数字化时代的浪潮中,IP地址扮演着不可或缺的角色。它们不仅是设备在网络中的唯一标识,更是网络连接和信息传输的基石。然而,对于非专业人士来说,IP地址的复杂分类可能会显得有些晦涩难懂。今天,我们就来深入探索IP地…

C#语言中的Async/await最佳实践

自从 C# 5 中引入 async/await 以来,开发人员之间一直对 async/await 关键字的最佳实践以及幕后实际发生的事情感到困惑。 让我们先从基础开始。 在 Windows 窗体的早期,UI 延迟与 I/O 操作所花费的时间成正比。这意味着,如果您尝试将数据保…

【ONE·基础算法 || 记忆化搜索】

总言 主要内容:编程题举例,熟悉理解记忆化搜索类题型(对比递归、动态规划理解运用)。             文章目录 总言1、记忆化搜索1.1、基本介绍1.2、细节理解(记忆搜索化、递归、动态规划……) 2、斐…

如何通过小猪APP分发轻松实现Web封装APP

你有没有想过将你的网站或者Web应用变成一个真正的APP?这听起来可能有点复杂,但其实在今天的技术环境下,这已经变得非常简单了。特别是有了像小猪APP分发这样的工具,你可以轻松地将你的Web应用封装成一个APP。 为什么要将Web应用封…

Java学习55-super关键字的使用

1.举例1:子类继承父类以后,对父类方法进行了重写,那么在子类中,是否还可以对父类中被重写的方法进行调用? 可以! 举例2:子类继承父类以后,发现子类和父类中定义了同名的属性&#xf…

示例:WPF中在没有MouseDoubleClick的控件中如何识别双击

一、目的&#xff1a;由于MouseDoubleClick控件是在Control中实现&#xff0c;那么在底层控件如Grid中想要类似功能如何实现&#xff0c;这里通过MouseDown的事MouseButtonEventArgs参数去实现 二、实现 定义Grid并注册Grid的MouseDown事件 <Grid Background"Transpa…

Android如何简单快速实现RecycleView的拖动重排序功能

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 要实现这个拖动重排序功能&#xff0c;主要是用到了RecycleView的ItemTouchHelper类 首先是定义一个接口 interface ItemTouchHelperAdapter …

哈尔滨等保测评如何办理

随着人们对网络安全的认识日益加深&#xff0c;越来越多的企业和组织开始重视网络安全等级保护工作。在哈尔滨地区&#xff0c;为了保证网络的安全&#xff0c;等保测评是保障网络安全的重要一环。本文对哈尔滨等保测评的流程、测评具体内容以及注意事项进行了详细地阐述。 一…

0X0-基于Sklearn的机器学习入门:聚类(上)

本节及后续章节将介绍深度学习中的几种聚类算法&#xff0c;所选方法都在Sklearn库中聚类模块有具体实现。本节为上篇&#xff0c;将介绍几种相对基础的聚类算法&#xff0c;包括K-均值算法和均值漂移算法。 目录 X.1 聚类概述 X.1.1 聚类的种类 X.1.2 Sklearn聚类子模块 …

纯css实现炫光流彩Button

正文 先看效果 实现思路 不仔细看的话还以为只需要通过animation与text-shadow、box-shadow、background-image就可以实现 仔细看的话会发现&#xff0c;其实按钮的颜色不是简单的渐变&#xff0c;而是从一侧颜色开始变化&#xff0c;渐渐的颜色蔓延到另一侧&#xff0c;之后…