MQ面试题3

1、讲一讲Kafka与RocketMQ中存储设计的异同?

Kafka 中文件的布局是以 Topic/partition ,每一个分区一个物理文件夹,在分区文件级别实现文件顺序写,如果一个Kafka集群中拥有成百上千个主题,每一个主题拥有上百个分区,消息在高并发写入时,其IO操作就会显得零散(消息分散的落盘策略会导致磁盘IO竞争激烈成为瓶颈),其操作相当于随机IO,即 Kafka 在消息写入时的IO性能会随着 topic 、分区数量的增长,其写入性能会先上升,然后下降。

而RocketMQ在消息写入时追求极致的顺序写,所有的消息不分主题一律顺序写入 commitlog 文件,并不会随着 topic 和 分区数量的增加而影响其顺序性。

在消息发送端,消费端共存的场景下,随着Topic数的增加Kafka吞吐量会急剧下降,而RocketMQ则表现稳定。因此Kafka适合Topic和消费端都比较少的业务场景,而RocketMQ更适合多Topic,多消费端的业务场景。

2、讲一讲Kafka与RocketMQ中零拷贝技术的运用

什么是零拷贝?

零拷贝(英语: Zero-copy) 技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

➢零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率

➢零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上:下文切换而带来的开销

可以看出没有说不需要拷贝,只是说减少冗余[不必要]的拷贝。

下面这些组件、框架中均使用了零拷贝技术:Kafka、Netty、Rocketmq、Nginx、Apache。

传统数据传送机制

比如:读取文件,再用socket发送出去,实际经过四次copy。

伪码实现如下:

buffer = File.read()

Socket.send(buffer)

1、第一次:将磁盘文件,读取到操作系统内核缓冲区;

2、第二次:将内核缓冲区的数据,copy到应用程序的buffer;

3、第三步:将application应用程序buffer中的数据,copy到socket网络发送缓冲区(属于操作系统内核的缓冲区);

4、第四次:将socket buffer的数据,copy到网卡,由网卡进行网络传输。

分析上述的过程,虽然引入DMA来接管CPU的中断请求,但四次copy是存在“不必要的拷贝”的。实际上并不需要第二个和第三个数据副本。应用程序除了缓存数据并将其传输回套接字缓冲区之外什么都不做。相反,数据可以直接从读缓冲区传输到套接字缓冲区。

显然,第二次和第三次数据copy 其实在这种场景下没有什么帮助反而带来开销(DMA拷贝速度一般比CPU拷贝速度快一个数量级),这也正是零拷贝出现的背景和意义。

打个比喻:200M的数据,读取文件,再用socket发送出去,实际经过四次copy(2次cpu拷贝每次100ms ,2次DMS拷贝每次10ms)

传统网络传输的话:合计耗时将有220ms

mmap内存映射(RocketMQ使用的)

硬盘上文件的位置和应用程序缓冲区(application buffers)进行映射(建立一种一一对应关系),由于mmap()将文件直接映射到用户空间,所以实际文件读取时根据这个映射关系,直接将文件从硬盘拷贝到用户空间,只进行了一次数据拷贝,不再有文件内容从硬盘拷贝到内核空间的一个缓冲区。

mmap内存映射将会经历:3次拷贝: 1次cpu copy,2次DMA copy;

打个比喻:200M的数据,读取文件,再用socket发送出去,如果是使用MMAP实际经过三次copy(1次cpu拷贝每次100ms ,2次DMS拷贝每次10ms)合计只需要120ms

从数据拷贝的角度上来看,就比传统的网络传输,性能提升了近一倍。

RocketMQ源码中的MMAP运用

RocketMQ源码中,使用MappedFile这个类类进行MMAP的映射

Kafka中的零拷贝

Kafka两个重要过程都使用了零拷贝技术,且都是操作系统层面的狭义零拷贝,一是Producer生产的数据存到broker,二是 Consumer从broker读取数据。

Producer生产的数据持久化到broker,采用mmap文件映射,实现顺序的快速写入;

Customer从broker读取数据,采用sendfile,将磁盘文件读到OS内核缓冲区后,直接转到socket buffer进行网络发送。

sendfile

linux 2.1支持的sendfile

当调用sendfile()时,DMA将磁盘数据复制到kernel buffer,然后将内核中的kernel buffer直接拷贝到socket buffer。在硬件支持的情况下,甚至数据都并不需要被真正复制到socket关联的缓冲区内。取而代之的是,只有记录数据位置和长度的描述符被加入到socket缓冲区中,DMA模块将数据直接从内核缓冲区传递给协议引擎,从而消除了遗留的最后一次复制。

一旦数据全都拷贝到socket buffer,sendfile()系统调用将会return、代表数据转化的完成。socket buffer里的数据就能在网络传输了。

sendfile会经历:3次拷贝,1次CPU copy ,2次DMA copy;硬件支持的情况下,则是2次拷贝,0次CPU copy, 2次DMA copy。

3、有没有读过RocketMQ源码,分享一下?

RocketMQ的源码是非常的多,我们没有必要把RocketMQ所有的源码都读完,所以我们把核心、重点的源码进行解读,RocketMQ核心流程如下:

  • 启动流程RocketMQ服务端由两部分组成NameServer和Broker,NameServer是服务的注册中心,Broker会把自己的地址注册到NameServer,生产者和消费者启动的时候会先从NameServer获取Broker的地址,再去从Broker发送和接受消息。
  • 消息生产流程Producer将消息写入到RocketMQ集群中Broker中具体的Queue。
  • 消息消费流程Comsumer从RocketMQ集群中拉取对应的消息并进行消费确认。

NameServer设计亮点

存储基于内存

NameServer存储以下信息:

topicQueueTable:Topic消息队列路由信息,消息发送时根据路由表进行负载均衡

brokerAddrTable:Broker基础信息,包括brokerName、所属集群名称、主备Broker地址

clusterAddrTable:Broker集群信息,存储集群中所有Broker名称

brokerLiveTable:Broker状态信息,NameServer每次收到心跳包是会替换该信息

filterServerTable:Broker上的FilterServer列表,用于类模式消息过滤。

NameServer的实现基于内存,NameServer并不会持久化路由信息,持久化的重任是交给Broker来完成。这样设计可以提高NameServer的处理能力。

消息写入流程

RocketMQ使用Netty处理网络,broker收到消息写入的请求就会进入SendMessageProcessor类中processRequest方法。

最终进入DefaultMessageStore类中asyncPutMessage方法进行消息的存储

然后消息进入commitlog类中的asyncPutMessage方法进行消息的存储

整个存储设计层次非常清晰,大致的层次如下图:

业务层:也可以称之为网络层,就是收到消息之后,一般交给SendMessageProcessor来分配(交给哪个业务来处理)。DefaultMessageStore,这个是存储层最核心的入口。

存储逻辑层:主要负责各种存储的逻辑,里面有很多跟存储同名的类。

存储I/O层:主要负责存储的具体的消息与I/O处理。

Commitlog写入时使用可重入锁还是自旋锁?

RocketMQ在写入消息到CommitLog中时,使用了锁机制,即同一时刻只有一个线程可以写CommitLog文件。CommitLog 中使用了两种锁,一个是自旋锁,另一个是重入锁。源码如下:

这里注意lock锁的标准用法是try-finally处理(防止死锁问题)

另外这里锁的类型可以自主配置。

RocketMQ 官方文档优化建议:异步刷盘建议使用自旋锁,同步刷盘建议使用重入锁,调整Broker配置项useReentrantLockWhenPutMessage,默认为false;

同步刷盘时,锁竞争激烈,会有较多的线程处于等待阻塞等待锁的状态,如果采用自旋锁会浪费很多的CPU时间,所以“同步刷盘建议使用重入锁”。

异步刷盘是间隔一定的时间刷一次盘,锁竞争不激烈,不会存在大量阻塞等待锁的线程,偶尔锁等待就自旋等待一下很短的时间,不要进行上下文切换了,所以采用自旋锁更合适。

Commitlog写入时使用可重入锁还是自旋锁?

RocketMQ在写入消息到CommitLog中时,使用了锁机制,即同一时刻只有一个线程可以写CommitLog文件。CommitLog 中使用了两种锁,一个是自旋锁,另一个是重入锁。源码如下:

这里注意lock锁的标准用法是try-finally处理(防止死锁问题)

另外这里锁的类型可以自主配置。

RocketMQ 官方文档优化建议:异步刷盘建议使用自旋锁,同步刷盘建议使用重入锁,调整Broker配置项useReentrantLockWhenPutMessage,默认为false;

同步刷盘时,锁竞争激烈,会有较多的线程处于等待阻塞等待锁的状态,如果采用自旋锁会浪费很多的CPU时间,所以“同步刷盘建议使用重入锁”。

异步刷盘是间隔一定的时间刷一次盘,锁竞争不激烈,不会存在大量阻塞等待锁的线程,偶尔锁等待就自旋等待一下很短的时间,不要进行上下文切换了,所以采用自旋锁更合适。

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

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

相关文章

Android AlarmManagerService-设置系统时间无效的问题

现象 使用系统接口设置时间生效,查看rtc也设置成功。但是重启后时间为首次开机的时间. 分析 多次测试后发现,设置时间在第一次开机时系统显示的时间之后,重启后时间设置生效;设置在之前,则会还原成第一次系统开机时显示的时间。 所以怀疑时,系统在开机的时候做了时间有效…

《Vue3+Typescript》一个简单的日历组件实现

这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~ 主页: oliver尹的主页 格言: 跌倒了爬起来就好~ 目录 一、…

SQL注入工具介绍——sqlmap

文章目录 一、安装方法二、使用方法三、sqlmap简介四、sqlmap支持的数据库五、检测注入1、基本格式2、跟随302跳转3、cookie注入4、从post数据包中注入 六、注入成功后1、获取数据库基本信息2、从数据库中搜索字段3、读取与写入文件 七、sqlmap详细命令1、Options(选…

架构的分类

目录 一、 RUP41 架构 1.1 RUP41架构方法概述 1.2 RUP41架构总体 1.3 RUP41架构方法内容 1.3.1 逻辑视图 1.3.2 开发视图 1.3.3 物理视图 1.3.4 处理视图 1.3.5 场景视图 ​二、 TOGAF9 架构 2.1 TOGAF9 架构概述 2.2 TOGAF9 架构分类 2.2.1 业务架构 2.2.2 数据架…

【1.3】Java微服务:Spring Cloud版本说明

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。 🍎个人主页:Meteors.的博客 💞当前专栏: 微服务 ✨特色专栏: 知识分享 &#x…

django4.2 day1Django快速入门

1、创建虚拟环境 打开cmd安装virtualenv pip install virtualenvwrapper-winworkon 查看虚拟环境mkvirtualenv 创建新的虚拟环境删除虚拟环境 rmvirtualenv 进入虚拟环境 workon env 2、创建django虚拟环境并安装django 创建虚拟环境mkvirtualenv django4env进入虚拟环境安…

每日一题(822. 翻转卡片游戏)-集合set

题目 822. 翻转卡片游戏 题解思路 简述为:找到桌面卡片中 不重复的最小值,卡片可以来回反转 如果 卡片前面后面的数字相同 则抛弃不用在剩下的卡片中 找到最小值(前后可以反转 卡片不分前后) 代码 C class Solution { pub…

Spring Boot Starter 剖析与实践 | 京东云技术团队

引言 对于 Java 开发人员来说,Spring 框架几乎是必不可少的。它是一个广泛用于开发企业应用程序的开源轻量级框架。近几年,Spring Boot 在传统 Spring 框架的基础上应运而生,不仅提供了 Spring 的全部功能,还使开发人员更加便捷地…

SpringSecurity自定义认证

Step 1: 创建自定义UserDetails类 自定义一个实现UserDetails接口的类,用于表示用户信息。您可以在这个类中添加自己需要的属性和方法来存储用户信息。 public class CustomUserDetails implements UserDetails {private String email;private boolean enabled;pri…

Redis 简介

文章目录 Redis 简介 Redis 简介 Redis(Remote Dictionary Server),远程词典服务器,基于 C/S 架构,是一个基于内存的键值型 NoSQL 数据库,开源,遵守 BSD 协议,Redis 由 C语言 实现。…

JS之new Date(‘yyyy-MM-dd‘)多8小时问题

new Date(‘yyyy-MM-dd’)多8小时问题 原因 //会多8小时的转化 new Date("2023-08-02") //不会多8小时的转化 new Date("2023-8-2")因为月和天为个位数时前面带有0,这时会当你处于格林尼治国际标准时的时区(0时区)而你…

线上服务出现异常,获取链接超时wait millis 60 000, active 0, maxActive 400, creating 1

背景 最近线上服务出现出现异常,导致整个服务数据库不可用,查看报错信息为:org.springframework.jdbc.CannotGetJdbcConnectionException:wait millis 60 000, active 0, maxActive 400, creating 1" druid版本&#xff1a…

P4145 上帝造题的七分钟 2 / 花神游历各国

上帝造题的七分钟 2 / 花神游历各国 题目背景 XLk 觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。 题目描述 "第一分钟,X 说,要有数列,于是便给定了一个正整数数列。 第二分钟,L 说,要能修改…

《向量数据库指南》——腾讯云向量数据库Tencent Cloud VectorDB产品特性,架构和应用场景

腾讯云向量数据库(Tencent Cloud VectorDB)是一款全托管的自研企业级分布式数据库服务,专用于存储、检索、分析多维向量数据。该数据库支持多种索引类型和相似度计算方法,单索引支持 10 亿级向量规模,可支持百万级 QPS 及毫秒级查询延迟。腾讯云向量数据库不仅能为大模型提…

前端Vue自定义精美商品分类组件category 可用于电商应用分类页面

随着技术的不断发展,传统的开发方式使得系统的复杂度越来越高。在传统开发过程中,一个小小的改动或者一个小功能的增加可能会导致整体逻辑的修改,造成牵一发而动全身的情况。为了解决这个问题,我们采用了组件化的开发模式。通过组…

MySQL踩坑之sql_mode的用法

目录 定义 报错重现 ​编辑 原因分析 sql_mode值说明 查看当前sql_mode 设置sql_mode 定义 什么是sql_mode?玩了这么久的MySQL语句࿰

SpringBoot整合Zookeeper

引入Jar包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>s…

JAVA开发工具-maven的安装与配置(最新最详细教程)

引言 Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的项目管理工具 软件。 Maven 除了以程序构建能力为特色之外&#xff0c;还提供高级项目管理工具。由于 Maven 的缺省构建规则有较 高的可重用性&#xff0c;所以常常用两…

模电专题-MOS管的放大电路分析

在实际应用中&#xff0c;我们经常会使用到功率MOS&#xff0c;这时通常不会将它当成一个开关使用&#xff0c;而是当成一个放大器来使用&#xff0c;那这就需要让其工作在放大状态。 参考下图中的mos管的特性曲线&#xff0c;右图中的输出特性曲线中有一根红色的分界线&#x…