消息队列面试

一、基础实战

(一)MQ的作用:异步、解耦、流量削峰填谷

(二)MQ应用场景

传统的金融项目一般使用IBMMQ(收费),比如某丰银行项目。ActiveMQ已经成为历史,因为现在很少使用。RabbitMQ(小项目使用较多)、Kafka(多用于大数据领域,支持大数据量的高并发吞吐量)、RocketMQ(支持10w/s的QPS)现在使用较多。
MQ应用场景

(三)RabbitMQ的AMQP

RabbitMQ的AMQP模型

1.交换机的类型

direct(直连交换机),fanout(广播交换机),topic(主题交换机),headers(和direct一样不实用可忽略)。

2.RabbitMQ消息可靠性分析

RabbitMQ消息可靠性分析

为了保证RabbitMQ消息不丢失,需要确保图片中①②③④四个环节都是ok的。

(1)发布者确认机制:确保消息生产者将消息成功发送到RabbitMQ服务器端

RabbitMQ支持发布确认(Publisher Confirm)机制,即消息生产者将消息发送到RabbitMQ服务器后,如果服务器端将消息成功存储到队列中则会返回一个确认消息给消息生产者,否则会返回一个否定消息Nack(Negative Acknowledgement)给消息生产者。

(2)备份队列:确保消息在交换机中不会丢失

RabbitMQ支持备份队列(Alternate Exchange)机制,即消息到达队列之前,先将消息发送到备份队列中。如果主队列无法接收消息,RabbitMQ会将消息发送到备份队列中。备份队列通常是一个交换机,可以在创建队列时通过x-dead-letter-exchange属性来指定备份队列。

(3)持久化:确保消息在队列中不会丢失

在发送消息时,可以设置消息属性delivery_mode为2,表示该消息需要被持久化,即将消息保存到磁盘中,即使RabbitMQ服务器宕机也能够保证消息不回丢失。可以在创建队列时将队列的durable持久化属性设置为True,表示该队列也需要被持久化,以便在RabbitMQ服务器宕机后能够重新创建队列和绑定。

(4)消费者确认机制:确保消费者成功消费消息

在RabbitMQ中,消费者通过basic.ack命令向RabbitMQ服务器确认已经消费了某条消息。如果消费者在处理消息时发生错误或者宕机,RabbitMQ服务器会重新将消息发送给其他消费者。在确认消息消费成功之前,RabbitMQ会将消息保存在内存(队列)中,只有收到消费者的确认消息后才会删除内存中的消息。
除了RabbitMQ本身会自动确认消息是否消费成功之外,还可以手动确认消息是否消费成功。

(四)Kafka:topic、partition(分区)

1.Kafka可靠性分析

Kafka可靠性分析。1个主题A包含2个分区,每个分区各有2个副本,落地到集群共2*2即4个分区

Kafka 通过多种机制来确保消息不丢失,包括副本机制、ISR(In-Sync Replicas)机制、ACK 机制等。

(1)副本机制

Kafka 通过副本机制来确保消息不会丢失。在 Kafka 中,每个分区都可以配置多个副本,每个副本保存分区的完整副本,当一个副本宕机时,Kafka 会自动将副本切换到其他可用的副本上。因此,即使其中一个副本宕机,也能够保证消息不会丢失。

(2)ISR 机制

在 Kafka 中,副本分为 Leader 副本和 Follower 副本。Leader 副本负责处理消息,Follower 副本只是简单地复制 Leader 副本的数据。当 Follower 副本落后于 Leader 副本时,Kafka 会将 Follower 副本从 ISR 中移除。只有当 Follower 副本与 Leader 副本的差距不大时,才会将 Follower 副本重新加入 ISR,确保消息不会丢失。

(3)ACK 机制

在 Kafka 中,生产者发送消息时可以指定 acks 参数,表示生产者等待的确认数。acks 参数有三个取值:
acks=0 表示生产者不等待确认消息,直接将消息发送到 Kafka 集群。这种方式可能会导致消息丢失,不建议使用。
acks=1 表示生产者在 Leader 副本收到消息后,就将消息视为发送成功。如果 Leader 副本在发送消息后立即宕机,消息可能会丢失。如果 Follower 副本成功复制了消息,但 Leader 副本在宕机前没有来得及将消息写入磁盘,则这条消息将会丢失。
acks=all 表示生产者在所有 ISR 副本都确认接收到消息后,才将消息视为发送成功。这种方式可以最大程度地确保消息不会丢失,但是会降低消息发送的性能。
通过上述机制的使用,可以最大程度地确保 Kafka 中的消息不会丢失。需要根据实际场景选择合适的参数配置来平衡消息发送的性能和可靠性。

(五)RocketMQ:topic、queue(队列)

1.RocketMQ可靠性分析

RocketMQ可靠性分析

RocketMQ 通过多种机制来确保消息不丢失,包括刷盘机制、消息拉取机制、ACK 机制等。

(1)刷盘机制

RocketMQ 中的消息分为内存消息和磁盘消息,内存消息在 Broker 内存中进行读写,磁盘消息则保存在磁盘上。RocketMQ 支持同步刷盘和异步刷盘两种方式,通过刷盘机制可以确保消息在 Broker 宕机时不会丢失。在同步刷盘模式下,消息写入磁盘时,会等待磁盘的写入完成才返回写入成功的响应。在异步刷盘模式下,消息写入磁盘后立即返回写入成功的响应,但是不等待磁盘写入完成。

(2)ACK 机制

在RocketMQ中,Producer发送消息后,Broker会返回ACK确认信号,表示消息已经成功发送。如果Broker没有收到ACK 确认信号,就会尝试重新发送该消息,直到消息被确认为止。
RocketMQ采用主从复制机制,每个消息队列都有一个主节点和多个从节点,主节点负责消息的写入和读取,从节点负责备份数据。当主节点宕机时,从节点会自动接管主节点的工作,确保消息不会丢失。

(3)消息存储机制

RocketMQ 默认使用双写模式来存储消息,即将消息同时写入内存和磁盘中,然后再将内存中的消息异步刷盘到磁盘中。这种方式可以保证消息的可靠性,即使系统宕机,也能够尽可能地保证消息不会丢失。
除此之外,RocketMQ 还提供了多种机制来保证消息不丢失,例如事务消息、延迟消息、顺序消息等,这些机制可以根据业务需求进行选择和使用。
需要注意的是,为了确保消息的可靠性,RocketMQ 的发送消息的速度可能会受到一定的限制,需要在消息可靠性和性能之间进行权衡。

2.RocketMQ生产架构

RocketMQ生产架构

(六)如何防止消息重复消费:消费端幂等性处理

1.什么是幂等性?

针对消息消费端来说,幂等性是指针对相同的输入多次调用处理函数得到的结果不变,也就是不管生产者发送多少次消息给消息消费端,对业务结果不会产生不期望的结果。
例如SQL语句update stat_table set count= 10 where id =1不管执行多少次,count字段的值都是10,那么执行SQL的操作就是幂等性操作。
再看另外一个SQL的执行就不是幂等性操作:update stat_table set count= count +1 where id= 1,因为每次执行SQL的结果都不一样。

2.如何实现幂等性?

(1)MVCC

多版本并发控制,一种乐观锁的实现。在生产者发送消息进行数据更新时需要带上数据的版本号,消费者去消费消息时需要比对数据的版本号,版本号不一致的操作无法成功。例如博客点赞次数自动加1的接口:

public boolean addCount(Long id, Long version);
update blogTable set count= count+1,version=version+1 where id=321 and version=123

每个version只有一次执行成功的机会,如果执行失败必须重新获取数据的最新版本号再次发起更新操作。

(2)去重表

利用数据库的特性来实现幂等,常用的一个思路就是在表上建立唯一性索引,保证某一类数据一旦执行完成,后续同样的请求将不再重复处理(利用一张日志表来记录已经处理成功的消息的id,如果新到的消息的id已经包含在日志表中,那么新到的这条消息就不在处理了)。
以电商平台为例,电商平台订单的id就是最适合的token。当用户下单时,会经历过很多个环节,比如生成订单、减库存、减优惠卷等等。请求经历每一个环节时先检查该订单id是否已经执行过这一步骤,对未执行的请求,执行操作并缓存执行结果,对已经执行过的id,则直接返回之前的执行结果,不做任何操作。这样以来,可以最大程度上减少重复执行的问题,缓存起来的执行结果也能用于事务控制等等。

二、高级实战

(一)什么是延时消息,各种MQ的实现?

1.场景

(1)买电影票

购票->选座位(选完座位后系统会锁定座位)->支付(限定5分钟内完成支付,否则释放座位)。
处理方案:锁定座位后,推送一条只有5分钟有效期的延时消息。应用中消费者进行业务处理时5分钟内没有完成支付系统将释放座位给其他用户购买。
如果不实用MQ,而是定时扫描数据库来解决需要延时处理的业务场景,这种方案性能差(不能保证即时性)、不灵活(系统的业务中可能还有其他不同的需要延时处理的场景)。

(2)实现
①通过RabbitMQ的死信队列/消息实现

基于死信交换机和两个消息队列实现的。先将消息发送到过期队列中,如果过一段时间后消息仍然没有被消费,那么消息将会进入死信队列中。一旦监控到死信队列中有消息说明消息没有及时被消费,这个时候可以做进一步处理。

②通过RocketMQ延时消息来实现

RocketMQ发送消息的方法有很多重载方法,可以根据业务中需要的延时时间精确度来选择不同的发送延时消息的方法,因为这些多个发送延时消息的重载方法的区别就是它们可以通过不同参数来决定延时消息的时间单位和精度。
RocketMQ延时消息的原理
生产者一旦发送了带有延时属性的消息,消息则不会立即进入目标主题,而是先进入一个临时主题(SCHEDULE_TOPIC_XXXX)。然后通过定时任务每秒运行一次去检查消息是否到达超时时间,如果消息到达超时时间会立即进入目标主题。
其中,SCHEDULE_TOPIC_XXXX主题有18个队列,每个队列对应一个延时消息等级,因为消息的延时等级有18个不同的时间。延时消息是放在队列中的,队列可以保证消息的顺序性,在定时任务遍历队列的时候只需要判断第一次消息是否过期,如果没有过期,那么其后面的消息肯定没有过期。

③Kafka自身没有延时消息的实现

(二)如何保证消息的顺序性?

最好生产者是单线程,如果是多线程并发生成消息就无法保证顺序性;
一个主题应该只有一个Queue;
消费者只能启动一个。

1.RabbitMQ消息存放在Queue队列中,因此自带顺序性

一条一条消费,一条消息消费完成后会从队列中删除。

(三)如何解决消息堆积问题?

RocketMQ和RabbitMQ可以通过后台管理界面监控消息是否出现堆积。

1.消费端

检查消费端代码,排查消息堆积是否是消息消费端的原因,如果是则需要代码解决。

2.突发流量

代码没有问题,数据库也没有锁的问题,这个时候需要排查是否是突发流量造成问题。假如有100w消息出现堆积,此时需要通过动态扩容机制来解决问题,具体来说是让多个消费者并发消费。

(四)RocketMQ的分布式事务

两阶段提交+消费者尽最大可能+失败补偿(利用消息队列的死信消息进行补偿)。
两阶段提交流程

三、原理与源码

(一)Kafka的ISR机制:(In Sync Replica)动态复制方案

Kafka中存在副本机制,一个Broker可能有多个副本Broker,每个Broker里面有进行分区p0、p1、p2、p3…。Broker推荐使用手动创建。
Kafka中存在ACKS确认机制。

1.acks=0

只要发送确认就可以了,只要消息到Kafka就认为这个消息已经写入Kafka。优点:速度快。缺点:有可能会消息丢失。

2.acks=1

至少有一个Leader写入到分区数据文件(因为RocketMQ采用内存映射方式,所以不需要保证数据一定存入磁盘)

3.acks=all

等到所有的同步副本都收到消息,Kafka才会确认消息写入成功。
如果要确保消息不丢失。那么最好要等到所有副本中的消息同步到Follower节点。
通过min.insync.replica参数值来控制消费端能够消费到的最小副本数。如果参数值为3那么在T1时刻只能消费到消息m1;如果参数值为2那么在T1时刻可以消费到m1和m2两条消息;如果参数值为3那么在T1时刻可以同时消费到m1、m2、m3三条消息

(二)零拷贝原理以及MQ的运用

零拷贝技术并不是说不涉及数据拷贝,而是指减少数据传输过程中的不必要数据拷贝次数。Kafka、RocketMQ、Nginx中都用到了零拷贝技术,通过文件映射的方式将磁盘和内存进行映射,修改内存中值后磁盘中的值会自动更改。RocketMQ在启动的时候把对应的文件做了内存映射,可以减少一次CPU拷贝。

1.请求到达操作系统后其内部处理机制

请求到达操作系统后其内部处理机制

2.传统网络传输(本地磁盘数据发送到远程服务器)

(1)流程执行:四次拷贝

数据从磁盘DMA拷贝到内核文件缓冲区->内核缓冲区的数据经过CPU拷贝到达用户空间内存缓冲区->数据在内存中修改后再经过一次CPU拷贝到达内核空间的Socket缓冲区->内核空间Socket缓冲区数据再经过一次DMA拷贝到达远程服务的网卡。
本地磁盘上的数据发送到远程服务器上需要经历两次DMA拷贝和两次CPU拷贝

(2)代码示例
①Server端实现

传统网络传输方式中的Server端实现

②Client端实现(4次拷贝):传统io读写+网络传输

客户端代码上半部分
客户端代码下半部分

3.零拷贝读写客户端(模仿Kafka中2次拷贝的sendfile方式)

模仿Kafka中2次拷贝的sendfile方式

(1)零拷贝和传统网络传输方式效率对比

可以发现零拷贝方式发送相同字节数需要的时间会短很多,文件越大其对比效果越明显。
传统网络传输(4次拷贝)方式用时215ms
零拷贝方式用时16ms

4.RocketMQ中零拷贝技术:通过Mmap文件映射方式的sendfile方法

RocketMQ中零拷贝技术的运用

(1)sendfile的零拷贝:发送文件描述符

Kafka中使用fileChannel.transferTo方式实现零拷贝,RocketMQ中使用文件映射方式具体来说是调用sendfile方法实现。transferTo方式内部本质上是封装了sendfile方式。
sendfile的零拷贝:发送文件描述符

(2)自定义代码实现Mmap零拷贝

Mmap零拷贝上半部分代码

(三)RocketMQ中Netty框架的运用

Netty框架中的数据流走向

1.RocketMQ是基于Netty框架的通讯模型实现的

(1)Netty框架:基于NIO事件驱动的异步通讯
(2)RocketMQ里面简化了客户端、服务端的Remoting类
(3)根据RequestCode来调用不同的处理器来实现不同的功能
(4)大量使用JUC里面的阻塞唤醒模型将异步转化为同步调用

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

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

相关文章

Redis 篇-深入了解基于 Redis 实现消息队列(比较基于 List 实现消息队列、基于 PubSub 发布订阅模型之间的区别)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 消息队列的认识 2.0 基于 List 实现消息队列 2.1 基于 List 实现消息队列的优缺点 3.0 基于 PubSub 实现消息队列 3.1 基于 PubSub 的消息队列优缺点 4.0 基于 St…

Unity数据持久化 之 使用Excel.DLL读写Excel表格

本文仅作笔记学习和分享,不用做任何商业用途 本文包括但不限于unity官方手册,unity唐老狮等教程知识,如有不足还请斧正​​ 终于找到一个比较方便容易读表的方式了,以前用json读写excel转的cvs格式文件我怎么使用怎么别扭&#xf…

AlmaLinux 9 上配置静态 IP 地址

在 Rocky Linux 9 中,密钥文件的新默认存储位置在 /etc/NetworkManager/system-connections 中 cd /etc/NetworkManager/system-connections默认dhcp配置 ~ …

免费SSL证书正在逐渐被淘汰,证书部署自动化的发展趋势即将到来!

目录 背景解决方案。1.使用自签证书(浏览器报警、免费)2.更换支持自签自续的CA机构(免费)3.付费选择CA机构 免费SSL证书正在逐渐被淘汰,证书部署自动化的发展趋势即将到来免费的SSL证书有以下弊端1.有效期短&#xff1…

stm32驱动开发与linux驱动的区别

stm32,gpio设置原理 下图,定义了gpio E的基地址,只要将这个地址强制转换成gpiotypedf的类型,解析时,结构体地址就会自增。这样就可以对不同gpio组,就像定义。 全部gpio定义,强制为结构体类型…

Linux CentOS更换阿里云源解决Could not retrieve mirrorlist http://mirrorlist.centos.org

Linux CentOS7 更新yum 操作的时候出现这个问题: Loading mirror speeds from cached hostfile Could not retrieve mirrorlist http://mirrorlist.centos.org 然后我执行 grep -nr "mirrorlist.centos.org" /etc/yum.repos.d/* 出现 这个问题时可以…

搭建 WordPress 及常见问题与解决办法

浪浪云活动链接 :https://langlangy.cn/?i8afa52 文章目录 环境准备安装 LAMP 堆栈 (Linux, Apache, MySQL, PHP)配置 MySQL 数据库 安装 WordPress配置 WordPress常见问题及解决办法数据库连接错误白屏问题插件或主题冲突内存限制错误 本文旨在介绍如何在服务器上…

爬虫使用代理IP后报错?解决方案在这里!

在数据抓取的过程中,使用代理IP是避免被封禁、提高抓取效率的重要手段。然而,有时候即使配置了代理IP,依然会遇到各种报错问题。本文将详细解析常见的报错类型,并提供解决方案,帮助你顺利进行数据抓取。 常见报错类型…

MySQL表的操作与数据类型

目录 前言 一、表的操作 1.创建一个表 2.查看表的结构 3.修改表 4.删除一个表 二、 MySQL的数据类型 0.数据类型一览: 1.整数类型 2.位类型 3.小数类型 4.字符类型 前言 在MySQL库的操作一文中介绍了有关MySQL库的操作,本节要讲解的是由库管理的结构——…

智能体 vs AI智能体:区别与联系,一文读懂!

​ 在AI技术蓬勃发展的今天,“智能体”(Agent)和”AI智能体”(AI Agent)两个概念经常被提及,二者在很多场合下会被混淆,但其实它们有着不同的定义和应用。我觉得很有必要小小科普下两者的定义与…

软件测试学习笔记丨Pytest的使用

本文转自测试人社区,原文链接:https://ceshiren.com/t/topic/22158 1. 简介 pytest是一个成熟的全功能python测试框架测试用例的skip和xfail,自动失败重试等处理能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/ap…

HTML的块级元素与行内元素

在HTML中,元素可以分为两大类:块级元素(block-level elements)和行内元素(inline elements)。这两种类型的元素在网页布局和呈现中扮演着不同的角色。 块级元素(Block-level Elements&#xff…

CMU 10423 Generative AI:HW1(编程部分:在GPT-2模型中实现RoPE、GQA)

完整代码和PDF笔记:https://github.com/YM2025/CMU_10423_2024S 文章目录 1 概述Rotary Positional Embeddings (RoPE)Grouped Query Attention (GQA)实验任务 2 项目文件1. requirements.txt2. input.txt3. chargpt.py4. mingpt/a. model.pyb. trainer.pyc. utils.…

毕业论文选题难?5招帮你轻松搞定选题!

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 你是不是已经为毕业论文的选题愁得头发都要掉光了?每次打开文档,都觉得什么都想写,又好像什么都写不了。选题看起来很简单,但真正开始动手的时候,…

深入探索系统架构设计

目录 前言 软件的体系结构 软件架构定义 软件架构设计与生命周期 1、需求分析阶段 2、设计阶段 3、实现阶段 4、构件组装阶段 5、部署阶段 6、后开发阶段 软件架构的重要性 1、架构设计能够满足系统的品质 2、架构设计使受益人达成一致的目标 3、架构设计能够支持…

UDS 诊断 - RequestTransferExit(请求传输终止)(0x37)服务

UDS 诊断服务系列文章目录 诊断和通信管理功能单元 UDS 诊断 - DiagnosticSessionControl(诊断会话控制)(0x10)服务 UDS 诊断 - ECUReset(ECU重置)(0x11)服务 UDS 诊断 - SecurityA…

【北京迅为】《STM32MP157开发板使用手册》- 第二十六章Cortex-M4 GPIO_蜂鸣器实验

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器,既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构,主频650M、1G内存、8G存储,核心板采用工业级板对板连接器,高可靠,牢固耐…

matlab 基于选权迭代法的空间平面拟合

目录 一、算法原理1、参数平差2、选权迭代法3、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的抄袭狗。 一、算法原理 1、参数平差 由空间几何学知,空间平面方程可以表述为: A x…

【C++】——string类的模拟实现

目录 一、string模拟实现 1.1构造析构 1.2迭代器 1.3修改 1.4查找 1.5substr 深浅拷贝的区别 1.6比较函数与流插入流提取 二、string类的拷贝 2.1浅拷贝与深拷贝 2.2传统版与现代版区别 2.3写时拷贝(了解) 三、vs和g下string结构的说明 3.1v…

零信任沙箱让源代码防泄漏“如虎添翼”

"数据泄露事件频发,给企业带来了巨大的经济损失和声誉损害。SDC沙盒,一款基于零信任模型构建的数据防泄密解决方案,正成为企业数据安全的新防线。 🔐 零信任模型的核心:SDC沙盒遵循“永不信任,始终验…