Kafka 物理存储机制

优质博文:IT-BLOG-CN

一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一。下面将从Kafka文件存储机制和物理结构角度,分析Kafka是如何实现高效文件存储,及实际应用效果。Kafka的基本存储单位是分区。在配置Kafka的时候,管理员指定了一个用于存储分区的目录清单log.dirs参数的值。

一、分区分配

创建主题时,Kafka首先决定如何在broker之间分配分区。假设有6broker,打算创建一个包含10个分区的主题。并且复制系数是3,相当于30个分区副本。在被分配到6broker上时,要达到如下的目标:
【1】在broker间平均分配分区副本。对于上述例子来说,就是要保证每个broker可以分到5个副本。
【2】确保每个分区的每个副本分布在不同的broker上。
【3】如果为broker指定了机架信息,那么尽可能把每个分区的副本分配到不同机架的broker上。这样做是为了保证一个机架不可用不会导致整个分区不可用。

为了实现这个目标,我们先随机选择一个broker(假设是2),然后通过轮询给每个broker分配分区来确定首领的位置。如果分区0的首领在broker2上,那么分区1的首领就在broker3上,以此类推。然后,从分区首领开始,以此分配跟随者副本。如分区0首领在broker2上,那么它的第一个副本会出现在broker3上,第二个出现在 broker4上。如果配置了机架信息,那么就不是按照数字顺序来选择broker了,而是按照交替机架的方式来选择broker。假设broker0broker1broker2放在同一个机架,broker3broker4broker5放在其他不同的机架。此时就不是按照05的顺序来选择broker,而是按照0,3,1,4,2,5的顺序进行选择的。

二、文件管理

保留数据时Kafka的一个基本特性,Kafka不会一直保留数据,也不会等到所有消费者都读取了消息之后才删除消息。相反,Kafka管理员为每个主题配置了数据保留期限,规定数据被删除之前可以保留多长时间,或者清理数据之前可以保留的数据量大小。 因为在一个大文件里查找和删除消息是很费时的,也很容易出错,所以我们把分区分成若干个片段。默认情况下,index大小为10M,每个片段log包含1GB或一周数据,以较小的那个为准。当前正在写入数据的片段叫做活跃片段,活跃片段永远不会被删除。

三、文件格式

我们把Kafka的消息和偏移量保存在文件里。保存在磁盘上的数据格式与从生产者发送过来或者发送给消费者的消息格式是一样的。因为使用相同的消息格式进行磁盘存储和网络传输,Kafka可以使用零复制技术给消费者发送消息,同时避免了对生产者已经压缩过的消息进行解压缩。除了键、值和偏移量外,消息里还包含了消息大小、校验和、消息格式版本号、压缩算法和时间戳。时间戳可以是生产者发送消息的时间,也可以是消息到达broker的时间,这个是可配置的。如果生产者发送的是压缩过的消息,那么同一个批次的消息会被再压缩一次,被当做包装消息进行发送。下面是普通消息和包装消息图:

四、文件存储机制

【1】Broker 消息中间件处理结点,一个Kafka节点就是一个Broker,多个Broker可以组成一个Kafka集群。
【2】Topic 主题,如page view日志、click日志等都可以以Topic的形式存在,Kafka集群能够同时负责多个Topic的分发。
【3】Partition Topic物理上的分组,一个Topic可以分为多个Partition,每个Partition是一个有序的队列。
【4】Segment Partition物理上由多个Segment组成。
【5】offset 每个 Partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到Partition中。Partition中的每个消息都有一个连续的序列号叫做offset,用于Partition唯一标识一条消息。

分析过程分为以下4个步骤:

【1】TopicPartition存储分布: 假设Kafka集群只有一个Brokerxxx/message-folder为数据文件存储根目录,在Kafka Brokerserver.properties文件配置(参数log.dirs=xxx/message-folder),例如创建2Topic名称分别为report_pushlaunch_infoPartitions数量都为partitions=4(将一个Topic分为4个部分存储)存储路径和目录规则为:

xxx/message-folder
|--report_push-0
|--report_push-1
|--report_push-2
|--report_push-3
|--launch_info-0
|--launch_info-1
|--launch_info-2
|--launch_info-3

【2】Partiton中文件存储方式: 每个Partion(目录)相当于一个巨型文件被平均分配到多个大小相等Segment(段)数据文件中。但每个段Segment file消息数量不一定相等,这种特性方便old segment file快速被删除。每个Partiton只需要支持顺序读写就行了,Segment文件生命周期由服务端配置参数决定。这样做的好处就是能快速删除无用文件,有效提高磁盘利用率。

【3】partitonsegment文件存储结构:segment file2大部分组成,分别为index filedata file,此2个文件成对出现,后缀".index"“.log”分别表示为segment索引文件、数据文件。segment文件命名规则:partion全局的第一个segment0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值。数值最大为64long大小,19位数字字符长度,没有数字用0填充。下面文件列表是笔者在Kafka broker上做的一个实验,创建一个topicXXX包含1 partition,设置每个segment大小为500MB,并启动producerKafka broker写入大量数据,如下图所示segment文件列表形象说明了上述2个规则以及segmentindex<—->data file对应关系物理结构如下:

索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。 其中以索引文件中元数据3,497为例,依次在数据文件中表示第3message(在全局partiton表示第368772message)、以及该消息的物理偏移地址为497。从上述图3了解到segment data file由许多 message组成,下面详细说明message物理结构如下:

【参数说明】:
8 byte offset:在Parition(分区)内的每条消息都有一个有序的id号,这个id号被称为偏移offset,它可以唯一确定每条消息在Parition内的位置。即offset表示Partiion的第多少message
4 byte message sizemessage大小;
4 byte CRC32:用crc32校验message
1 byte “magic":表示本次发布Kafka服务程序协议版本号;
1 byte “attributes":表示为独立版本、或标识压缩类型、或编码类型;
4 byte key length:表示key的长度,当key-1时,K byte key字段不填;
value bytes payload:表示实际消息数据;

`index文件结构:

offset: 783932 position: 69483992
offset: 784323 position: 69543233
offset: 784565 position: 69589443
offset: 784932 position: 69623433
offset: 785355 position: 69658994
offset: 785894 position: 69704355
offset: 786389 position: 69738993
offset: 786584 position: 69784345

log文件结构: 有个眼缘即可

offset: 784932 CreateTime:1598161852389 keysize: -1 valuesize: 15 sequence: 9884 baseOffset: 7043213 lastOffset: 784932 count: 1 baseSequence: 907

【4】在partition中如何通过offset查找message 例如读取offset=368776Message,需要通过下面2个步骤查找。
【第一步】查找segment file 上图为例,其中00000000000000000000.index表示最开始的文件,起始偏移量offset为0。第二个文件00000000000000368769.index的消息量起始偏移量为368770 = 368769 + 1。同样,第三个文件00000000000000737337.index的起始偏移量为737338=737337 + 1,其他后续文件依次类推,以起始偏移量命名并排序这些文件,只要根据offset二分查找文件列表,就可以快速定位到具体文件。当offset=368776时定位到00000000000000368769.index|log
【第二步】通过segment file查找message 通过第一步定位到segment file,当offset=368776时,依次定位到00000000000000368769.index 的元数据物理位置和00000000000000368769.log的物理偏移地址,然后再通过00000000000000368769.log顺序查找直到offset=368776为止。从上述图可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。通过上述过程详细分析,我们就可以清楚认识到kafka文件存储机制的奥秘。

五、Kafka文件实际运行效果

【实验环境】:Kafka集群 = 由2台虚拟机组成;CPU = 4核;物理内存= 8GB;网卡 = 千兆网卡;JVM HEAP = 4GB;详细Kafka服务端配置及其优化请参考:Kafka server.properties配置详解:

从上述图可以看出,Kafka运行时很少有大量读磁盘的操作,主要是定期批量写磁盘操作,因此操作磁盘很高效。这跟Kafka文件存储中读写message的设计是息息相关的。Kafka中读写message有如下特点:写message,消息从java堆转入page cache即物理内存。由异步线程刷盘,消息从page cache刷入磁盘。读message消息直接从page cache转入socket发送出去。当从page cache没有找到相应数据时,此时会产生磁盘IO,从磁盘Load消息到page cache,然后直接从socket发出去。

六、Kafka 中的 Partition 和 Offset

【1】Log机制: 说到分区,就要说Kafka对消息的存储,首先,kafka是通过log(日志)来记录消息发布的。每当产生一个消息,Kafka会记录到本地的log文件中,这个log和我们平时的log有一定的区别。这里可以参考一下The Log,不多解释。这个log文件默认的位置在config/server.properties中指定的,默认的位置是log.dirs=/tmp/kafka-logsLinux不用说,windows的话就在你对应磁盘的根目录下。

分区Partition Kafka是为分布式环境设计的,因此如果日志文件,其实也可以理解成消息数据库,放在同一个地方,那么必然会带来可用性的下降,一挂全挂,如果全量拷贝到所有的机器上,那么数据又存在过多的冗余,而且由于每台机器的磁盘大小是有限的,所以即使有再多的机器,可处理的消息还是被磁盘所限制,无法超越当前磁盘大小。因此有了Partition的概念。Kafka对消息进行一定的计算,通过hash来进行分区。这样,就把一份log文件分成了多份。如上面的分区读写日志图,分成多份以后,在单台Broker上,比如快速上手中,如果新建Topic的时候,我们选择replication-factor 1 partitions 2,那么在log目录里,我们会看到test-0目录和test-1目录就是两个分区了。你可能会想,这没啥区别呀。注意,当有了多个broker之后,这个意义就存在了。这里上一张图:

【2】Kafka分布式分区存储: 这是一个Topic包含4Partition2 Replication(拷贝),也就是说全部的消息被放在了4个分区存储,为了高可用,将4个分区做了2份冗余,然后根据分配算法。将总共8份数据,分配到Broker集群上。结果就是每个Broker上存储的数据比全量数据要少,但每份数据都有冗余,这样,一旦一台机器宕机,并不影响使用。比如图中的Broker1,宕机了那么剩下的三台Broker依然保留了全量的分区数据。所以还能使用,如果再宕机一台,那么数据不完整了。当然你可以设置更多的冗余,比如设置了冗余是4,那么每台机器就有了0123完整的数据,宕机几台都行。需要在存储占用和高可用之间做衡量。至于宕机后,zookeeper会选出新的 partition leader

偏移offset 上一段说了分区,分区就是一个有序的,不可变的消息队列。新来的commit log持续往后面加数据。这些消息被分配了一个下标(或者偏移),就是offset,用来定位这一条消息。消费者消费到了哪条消息,是保持在消费者这一端的。消息者也可以控制,消费者可以在本地保存最后消息的offset,并间歇性的向zookeeper注册offset。也可以重置offset

如何通过offset算出分区:其实Partition存储的时候,又分成了多个segment(段),然后通过一个index索引,来标识第几段。这里先可以去看一下本地log目录的分区文件夹。在我这里,test-0这个分区里面,会有一个index文件和一个log文件,对于某个指定的分区,假设每5个消息作为一个段大小,当产生了10条消息的情况下,目前有会分段。
0.index(表示这里index是对0-4做的索引)、5.index (表示这里index是对5-9做的索引)、10.index (表示这里index是对10-15做的索引,目前还没满) 和0.log5.log10.log。当消费者需要读取offset=8的时候,首先kafkaindex文件列表进行二分查找,可以算出应该是在5.index对应的log文件中,然后对对应的5.log文件,进行顺序查找,5->6->7->8,直到顺序找到8就好了。

七、索引

消费者可以从Kafka的任意可用偏移量位置开始读取消息,假设消费者要读取从偏移量100开始的1MB消息,那么Broker必须立即定位到偏移量100,为了帮组broker更快地定位到指定的偏移量,Kafka为每个分区维护一个索引。索引把偏移量映射到片段文件和偏移量在文件里的位置。索引也被分成片段,所以再删除消息时,也可以删除相应的索引。Kafka不维护索引的校验和。如果索引出现损坏,Kafka会通过重新读取消息并录制偏移量和位置来重新生成索引。如果有必要,管理员是可以删除索引的,这样做是绝对安全的,Kafka会自动重新生成这些索引。

八、Kafka高效文件存储设计特点

【1】Kafkatopic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
【2】通过索引信息可以快速定位message和确定response的最大大小。
【3】通过index元数据全部映射到memory,可以避免segment fileIO磁盘操作。
【4】通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。

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

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

相关文章

采用STM32CubeMX和HAL库的定时器应用实例

目录 STM32的通用定时器配置流程 定时器应用的硬件设计 定时器应用的软件设计 1. 通过STM32CubeMX新建工程 通过STM32CubeMX新建工程的步骤如下&#xff1a; 2. 通过Keil MDK实现工程 通过Keil MDK实现工程的步骤如下&#xff1a; STM32的通用定时器配置流程 通用定时器…

【优选算法篇】前缀之序,后缀之章:于数列深处邂逅算法的光与影

文章目录 C 前缀和详解&#xff1a;基础题解与思维分析前言第一章&#xff1a;前缀和基础应用1.1 一维前缀和模板题解法&#xff08;前缀和&#xff09;图解分析C代码实现易错点提示代码解读题目解析总结 1.2 二维前缀和模板题解法&#xff08;二维前缀和&#xff09;图解分析C…

Topaz Video AI for Mac 视频无损放大软件安装教程【保姆级,操作简单轻松上手】

Mac分享吧 文章目录 Topaz Video AI for Mac 视频无损放大软件 安装完成&#xff0c;软件打开效果一、Topaz Video AI 视频无损放大软件 Mac电脑版——v5.3.5⚠️注意事项&#xff1a;1️⃣&#xff1a;下载软件2️⃣&#xff1a;安装软件&#xff0c;将安装包从左侧拖入右侧文…

CNAS软件测试的好处有哪些?上海软件测试中心推荐

在进行软件测试或其他项目检测需要选择软件测试中心时&#xff0c;我们常常会把该公司有无资质认证考虑进去。那么CNAS认可作为检测机构或实验室的一项重要资质认证&#xff0c;我们可能会产生疑问&#xff1a;CNAS认可什么意思?CNAS软件测试又有什么好处呢? 1、CNAS认可是什…

【51 Pandas+Pyecharts | 深圳市共享单车数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 处理起始时间、结束时间2.4 增加骑行时长区间列2.5 增加骑行里程区间列 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 各…

AMBA之AXI 总线

AMBA概述 AMBA&#xff08;Advanced Microcontroller Bus Architecture&#xff09;是ARM公司开发的一种高级微控制器总线架构&#xff0c;用于连接处理器、存储器和外设的通信。AMBA总线架构定义了一组协议和接口&#xff0c;用于实现高性能、低功耗、可扩展的系统设计。 AM…

Amcor 如何借助 Liquid UI 实现SAP PM可靠性

背景介绍 安姆科是塑料行业的全球领军企业&#xff0c;该企业认识到 SAP 工厂维护&#xff08;SAP PM&#xff09;对于确保高效的维护管理的重要性。 在诸如制造业等高度依赖机械设备的行业中&#xff0c;SAP PM是一种通过数据驱动决策来最大限度减少停机时间、降低间接成本、…

【C语言】预处理(预编译)详解(下)(C语言最终篇)

文章目录 一、#和##1.#运算符2.##运算符 二、预处理指令#undef三、条件编译1.单分支条件编译2.多分支条件编译3.判断符号是否被定义4.判断符号是否没有被定义 四、头文件的包含1.库头文件的包含2.本地头文件的包含3.嵌套包含头文件的解决方法使用条件编译指令使用预处理指令#pr…

宠物空气净化器哪个牌子好?有没有噪音低的宠物空气净化器推荐?

如今随着社会竞争越来越激烈&#xff0c;不少人开始焦虑内耗&#xff0c;但为了能更好的生活&#xff0c;养宠物便成为不少人的排忧解乏的方法。 我也不例外&#xff0c;作为一名996社畜&#xff0c;天刚亮就出门&#xff0c;天黑很久才回家&#xff0c;所以选择养猫来陪我度过…

C++设计模式创建型模式———生成器模式

文章目录 一、引言二、生成器/建造者模式三、总结 一、引言 上一篇文章我们介绍了工厂模式&#xff0c;工厂模式的主要特点是生成对象。当对象较简单时&#xff0c;可以使用简单工厂模式或工厂模式&#xff1b;而当对象相对复杂时&#xff0c;则可以选择使用抽象工厂模式。 工…

创作三周年:在忙碌中寻找灵感与快乐

目录 机缘 收获 技能的提升 粉丝的积累 正向的反馈 同行的伙伴 日常 运动 旅行 生活 憧憬 结语 机缘 不知不觉已经成为创作者3年了&#xff0c;这一路走来&#xff0c;有过高峰和低谷&#xff0c;但始终让我坚持的&#xff0c;是最初那份简单的初心&#xff1a;我…

C#从零开始学习(用户界面)(unity Lab4)

这是书本中第四个unity Lab 在这次实验中,将学习如何搭建一个开始界面 分数系统 点击球,会增加分数 public void ClickOnBall(){Score;}在OneBallBehaviour类添加下列方法 void OnMouseDown(){GameController controller Camera.main.GetComponent<GameController>();…

分布式搜索引擎elasticsearch操作文档操作介绍

1.DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0c;…

软件系统安全保证措施,质量保证措施方案(Word原件套用)

系统安全保证措施是构建稳固防御体系的核心&#xff0c;旨在全方位保障信息系统的安全性。以下是对这七项措施的简要概述&#xff1a; 一、身份鉴别&#xff1a;采用多种认证方式&#xff0c;如密码、生物识别等&#xff0c;确保用户身份的准确无误&#xff0c;防止非法入侵。 …

玩转Docker | 使用Docker部署捕鱼网页小游戏

玩转Docker | 使用Docker部署捕鱼网页小游戏 一、项目介绍项目简介项目预览 二、系统要求环境要求环境检查Docker版本检查检查操作系统版本 三、部署捕鱼网页小游戏下载镜像创建容器检查容器状态下载项目内容查看服务监听端口安全设置 四、访问捕鱼网页小游戏五、总结 一、项目…

局域网 docker pull 使用代理拉取镜像

局域网 docker pull 使用代理拉取镜像 1、需求&#xff1a; 我有win主机&#xff0c;上面装有代理可连接dockerhub&#xff1b;我另有linux主机&#xff0c;直接pull因墙失败&#xff0c;想走win的代理访问dockerhub拉镜像&#xff1b;两台主机在同一个局域网中&#xff1b; …

c语言中结构体传参和实现位段

结构体传参 有两种方法: #include<stdio.h> struct S {int data[1000];int num; }; //结构体传参 void print1(struct S s) {printf("%d\n",s.num); } //结构体地址传参 void print2(struct S *ps) {printf("%d\n",ps->num); }int main() {pr…

2024年10月HarmonyOS应用开发者基础认证全新题库

注意事项&#xff1a;切记在考试之外的设备上打开题库进行搜索&#xff0c;防止切屏三次考试自动结束&#xff0c;题目是乱序&#xff0c;每次考试&#xff0c;选项的顺序都不同 这是基础认证题库&#xff0c;不是高级认证题库注意看清楚标题 高级认证题库地址&#xff1a;20…

HTML3D旋转相册

文章目录 序号目录1HTML满屏跳动的爱心(可写字)2HTML五彩缤纷的爱心3HTML满屏漂浮爱心4HTML情人节快乐

Depcheck——专门用于检测 JavaScript 和 Node.js 项目中未使用依赖项的工具

文章目录 Depcheck 是什麽核心功能&#x1f4da;检测未使用的依赖&#x1f41b;检测缺失的依赖✨支持多种文件类型&#x1f30d;可扩展性 安装与使用1. 安装 Depcheck2. 使用 Depcheck Depcheck 的应用总结项目源码&#xff1a; Depcheck 是什麽 来看一个常见错误场景&#x1…