大数据技术之 Kafka (第 3 章 Kafka 架构深入 ) Log存储解析

Kafka 工作流程 

Kafka 中消息是以 topic 进行分类的,生产者生产消息,消费者消费消息,都是面向 topic的。 
topic 是逻辑上的概念,而 partition 是物理上的概念,每个 partition 对应于一个 log 文件,该 log 文件中存储的就是 producer 生产的数据。Producer 生产的数据会被不断追加到该log 文件末端,且每条数据都有自己的 offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个 offset,以便出错恢复时,从上次的位置继续消费 

Kafka文件存储机制

由于生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据定位效率低下,Kafka 采取了分片和索引机制,将每个 partition 分为多个 segment。每个 segment对应两个文件——“.index”文件和“.log”文件。这些文件位于一个文件夹下,该文件夹的命名规则为:topic 名称+分区序号。例如,first 这个 topic 有三个分区,则其对应的文件夹为 first0,first-1,first-2。

[root@backup01 logs]# cd /usr/local/hadoop/kafka/kafka_2.12-2.4.1/logs/first-0
[root@backup01 first-0]# ll
total 8
-rw-r--r--. 1 root root 10485760 Mar 29 16:32 00000000000000000000.index
-rw-r--r--. 1 root root      146 Mar 29 17:34 00000000000000000000.log
-rw-r--r--. 1 root root 10485756 Mar 29 16:32 00000000000000000000.timeindex
-rw-r--r--. 1 root root        8 Mar 29 16:32 leader-epoch-checkpoint
[root@backup01 first-0]# 

00000000000000000000.index 
00000000000000000000.log 
00000000000000170410.index 
00000000000000170410.log 
00000000000000239430.index 
00000000000000239430.log 

index 和 log 文件以当前 segment 的第一条消息的 offset 命名。下图为 index 文件和 log 文件的结构示意图

“.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元 数据指向对应数据文件中 message 的物理偏移地址。  

Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的。每个topic又可以分成几个不同的partition(每个topic有几个partition是在创建topic时指定的),每个partition存储一部分Message。借用官方的一张图,可以直观地看到topic和partition的关系。


partition是以文件的形式存储在文件系统中,比如,创建了一个名为page_visits的topic,其有5个partition,那么在Kafka的数据目录中(由配置文件中的log.dirs指定的)中就有这样5个目录: page_visits-0, page_visits-1,page_visits-2,page_visits-3,page_visits-4,其命名规则为<topic_name>-<partition_id>,里面存储的分别就是这5个partition的数据。

接下来,本文将分析partition目录中的文件的存储格式和相关的代码所在的位置。

Partition的数据文件

Partition中的每条Message由offset来表示它在这个partition中的偏移量,这个offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了partition中的一条Message。因此,可以认为offset是partition中Message的id。partition中的每条Message包含了以下三个属性:

   offset
    MessageSize
    data

其中offset为long型,MessageSize为int32,表示data有多大,data为message的具体内容。它的格式和Kafka通讯协议中介绍的MessageSet格式是一致。

Partition的数据文件则包含了若干条上述格式的Message,按offset由小到大排列在一起。它的实现类为FileMessageSet,类图如下:
FileMessageSet类图

它的主要方法如下:

append: 把给定的ByteBufferMessageSet中的Message写入到这个数据文件中。
searchFor: 从指定的startingPosition开始搜索找到第一个Message其offset是大于或者等于指定的offset,并返回其在文件中的位置Position。它的实现方式是从startingPosition开始读取12个字节,分别是当前MessageSet的offset和size。如果当前offset小于指定的offset,那么将position向后移动LogOverHead+MessageSize(其中LogOverHead为offset+messagesize,为12个字节)。
read:准确名字应该是slice,它截取其中一部分返回一个新的FileMessageSet。它不保证截取的位置数据的完整性。
sizeInBytes: 表示这个FileMessageSet占有了多少字节的空间。
truncateTo: 把这个文件截断,这个方法不保证截断位置的Message的完整性。
readInto: 从指定的相对位置开始把文件的内容读取到对应的ByteBuffer中。
我们来思考一下,如果一个partition只有一个数据文件会怎么样?

新数据是添加在文件末尾(调用FileMessageSet的append方法),不论文件数据文件有多大,这个操作永远都是O(1)的。
查找某个offset的Message(调用FileMessageSet的searchFor方法)是顺序查找的。因此,如果数据文件很大的话,查找的效率就低。
那Kafka是如何解决查找效率的的问题呢?有两大法宝:1) 分段 2) 索引。

数据文件的分段
Kafka解决查询效率的手段之一是将数据文件分段,比如有100条Message,它们的offset是从0到99。假设将数据文件分成5段,第一段为0-19,第二段为20-39,以此类推,每段放在一个单独的数据文件里面,数据文件以该段中最小的offset命名。这样在查找指定offset的Message的时候,用二分查找就可以定位到该Message在哪个段中。

为数据文件建索引
数据文件分段使得可以在一个较小的数据文件中查找对应offset的Message了,但是这依然需要顺序扫描才能找到对应offset的Message。为了进一步提高查找的效率,Kafka为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为.index。
索引文件中包含若干个索引条目,每个条目表示数据文件中一条Message的索引。索引包含两个部分(均为4个字节的数字),分别为相对offset和position。

相对offset:因为数据文件分段以后,每个数据文件的起始offset不为0,相对offset表示这条Message相对于其所属数据文件中最小的offset的大小。举例,分段后的一个数据文件的offset是从20开始,那么offset为25的Message在index文件中的相对offset就是25-20 = 5。存储相对offset可以减小索引文件占用的空间。
position,表示该条Message在数据文件中的绝对位置。只要打开文件并移动文件指针到这个position就可以读取对应的Message了。
index文件中并没有为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

在Kafka中,索引文件的实现类为OffsetIndex,它的类图如下:


主要的方法有:

append方法,添加一对offset和position到index文件中,这里的offset将会被转成相对的offset。
lookup, 用二分查找的方式去查找小于或等于给定offset的最大的那个offset
小结
我们以几张图来总结一下Message是如何在Kafka中存储的,以及如何查找指定offset的Message的。

Message是按照topic来组织,每个topic可以分成多个的partition,比如:有5个partition的名为为page_visits的topic的目录结构为:

partition是分段的,每个段叫LogSegment,包括了一个数据文件和一个索引文件,下图是某个partition目录下的文件:

可以看到,这个partition有4个LogSegment。

借用博主@lizhitao博客上的一张图来展示是如何查找Message的。

比如:要查找绝对offset为7的Message:

首先是用二分查找确定它是在哪个LogSegment中,自然是在第一个Segment中。
打开这个Segment的index文件,也是用二分查找找到offset小于或者等于指定offset的索引条目中最大的那个offset。自然offset为6的那个索引是我们要找的,通过索引文件我们知道offset为6的Message在数据文件中的位置为9807。
打开数据文件,从位置为9807的那个地方开始顺序扫描直到找到offset为7的那条Message。
这套机制是建立在offset是有序的。索引文件被映射到内存中,所以查找的速度还是很快的。

一句话,Kafka的Message存储采用了分区(partition),分段(LogSegment)和稀疏索引这几个手段来达到了高效性。
 

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

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

相关文章

推荐系统整体框架概览

推荐系统整体框架概览推荐系统整体架构 推荐系统的核心组成部分离线核心节点服务UI总结推荐系统整体架构 先说点题外话&#xff0c;最近在看的书中讲到了怎么进行自学的方法&#xff0c;分了十个层级。第一个便是要了解所学内容的概况&#xff0c;也就是轮廓&#xff0c;大的东…

大数据技术之 Kafka (第 3 章 Kafka 架构深入 ) Kafka 生产者

3.2.1 分区策略 1&#xff09;分区的原因 &#xff08;1&#xff09;方便在集群中扩展&#xff0c;每个 Partition 可以通过调整以适应它所在的机器&#xff0c;而一个 topic又可以有多个 Partition 组成&#xff0c;因此整个集群就可以适应任意大小的数据了&#xff1b; &a…

MySQL定时备份实现

一、备份数据库 –all-databases 备份所有数据库 /opt/mysqlcopy/all_$(date “%Y-%m-%d %H:%M:%S”).sql 备份地址 docker exec -it 容器名称 sh -c "mysqldump -u root -ppassword --all-databases > /opt/mysqlcopy/all_$(date "%Y-%m-%d %H:%M:%S").sq…

程序员健身的重要性

程序员健身的重要性人的身体就是人的灵魂最好的写照&#xff01; &#xff0d;&#xff0d;&#xff0d; 路德维系.维特根斯坦 健身不仅是保持健康体魄的关键要素之一&#xff0c;也是灵活的、具有创造性的脑力活动的基础。 &#xff0d;&#xff0d;&#xff0d; 约翰.肯尼迪 …

Java 8 中的哈希表

JDK 的代码是开源的&#xff0c;我们打开idea开发工具&#xff0c;引入jdk1.8 找到hashmap HashMap 是基于 HashTable 的一种数据结构&#xff0c;在普通哈希表的基础上&#xff0c;它支持多线程操作以及空的 key 和 value。 在 HashMap 中定义了几个常量: static final in…

NSJSONSerialization介绍

ios5中apple增加了解析JSON的api——NSJSONSerialization。网上已经有人做过测试&#xff0c;NSJSONSerialization在效率上完胜SBJSON、TouchJSON、YAJL、JSONKit、NextiveJson。详情见这里。既然apple为我们提供了这么良好的工具&#xff0c;我们没理由不用吧。 NSJSONSeriali…

[转帖]ISE与Modelsim联合观察中间信号

如何仿真IP核&#xff08;建立modelsim仿真库完整解析&#xff09; 来源&#xff1a;http://www.ednchina.com/ART_49023_19_0_AN_7116cf44.HTM IP核生成文件&#xff1a;&#xff08;Xilinx/Altera 同&#xff09; IP核生成器生成 ip 后有两个文件对我们比较有用&#xff0c;假…

sql server 2008学习12 事务和锁

事务 事务的点: 1.begin tran 是事务开始的地方,也是 事务回滚的起点.也就说他会忽略这个起点之后的最终没有提交的所有语句, 2.commit tran 事务的提交 是一个事务的终点 当发出 commit tran命令时,可以认为 该事务是 持久的. 撤销已完成事务的唯一方法 是 发出一个新的事务.…

漫画:什么是时间复杂度?

时间复杂度的意义 究竟什么是时间复杂度呢&#xff1f;让我们来想象一个场景&#xff1a;某一天&#xff0c;小灰和大黄同时加入了一个公司...... 一天过后&#xff0c;小灰和大黄各自交付了代码&#xff0c;两端代码实现的功能都差不多。大黄的代码运行一次要花100毫秒&#x…

NLP 最新进展

参考文献&#xff1a; •http://www.dataguru.cn/article-14237-1.html •https://zhuanlan.zhihu.com/p/46652512 •https://github.com/google-research/bert •https://allennlp.org/elmo •https://arxiv.org/pdf/1802.05365 •https://arxiv.org/abs/1810.04805

Big GAN

参考文献&#xff1a; •https://github.com/kayamin/DR-GAN •https://www.jianshu.com/p/4ee8f9284b81 •http://cvlab.cse.msu.edu/pdfs/Tran_Yin_Liu_CVPR2017.pdf •https://arxiv.org/abs/1809.11096 •https://juejin.im/entry/5c05e76c51882539c60cf2d5 •https:…

什么样的知识,值得我们终生学习

#什么样的知识&#xff0c;值得我们终生学习&#xff1f; 原文&#xff1a;https://dwz.cn/vylyXXJi 一、引言 可能你从初中就开始抱怨&#xff1a;我学相似三角形能干什么&#xff1f;阿伏伽德罗常数有什么用&#xff1f;我一不跳楼&#xff0c;二不高空抛物&#xff0c;学自由…

美团面试题:Hashmap的结构,1.7和1.8有哪些区别,深入的分析

&#xff08;一&#xff09; 真实面试题之&#xff1a;Hashmap的结构&#xff0c;1.7和1.8有哪些区别 不同点&#xff1a; &#xff08;1&#xff09;JDK1.7用的是头插法&#xff0c;而JDK1.8及之后使用的都是尾插法&#xff0c;那么他们为什么要这样做呢&#xff1f;因为JDK1…

大数据技术之 Kafka (第 3 章 Kafka 架构深入 ) Kafka 消费者

3.3.1 消费方式 consumer 采用 pull&#xff08;拉&#xff09;模式从 broker 中读取数据。 push&#xff08;推&#xff09;模式很难适应消费速率不同的消费者&#xff0c;因为消息发送速率是由 broker 决定的。 它的目标是尽可能以最快速度传递消息&#xff0c;但是这样很…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) offset讲解

新版的 Kafka 使用一个选举出来的 controller 来监听 zookeeper&#xff0c;其他 node 再去和 controller 通信&#xff0c;这么做的目的是为了减少 zookeeper 的压力。bootstrap-servers 会自动发现其他 broker&#xff0c;这也是 bootstrap 的含义 前面我们讲到了消费者&…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) 消费者组案例

1&#xff09;需求&#xff1a;测试同一个消费者组中的消费者&#xff0c;同一时刻只能有一个消费者消费。 2&#xff09;案例实操 &#xff08;1&#xff09;在 backupo01、backupo02 上修改/usr/local/hadoop/kafka/kafka_2.12-2.4.1/config/consumer.properties 配置 文件…

大数据技术之kafka (第 3 章 Kafka 架构深入 ) 高效读写数据

1&#xff09;顺序写磁盘 Kafka 的 producer 生产数据&#xff0c;要写入到 log 文件中&#xff0c;写的过程是一直追加到文件末端&#xff0c; 为顺序写。官网有数据表明&#xff0c;同样的磁盘&#xff0c;顺序写能到 600M/s&#xff0c;而随机写只有 100K/s。这 与磁盘的机…

大数据技术之kafka (第 3 章 Kafka 架构深入) Zookeeper 在 Kafka 中的作用

Kafka 集群中有一个 broker 会被选举为 Controller&#xff0c;负责管理集群 broker 的上下线&#xff0c;所有 topic 的分区副本分配和 leader 选举等工作。 Controller 的管理工作都是依赖于 Zookeeper 的。 以下为 partition 的 leader 选举过程&#xff1a; Leader选举流…

LinkedList源码阅分析

LinkedList里面涉及到的一些操作&#xff0c;非常细致&#xff0c;以避免出现的空指针&#xff0c;理解后对于其优点与确定会有一个更加整体的认识吧。 继承关系图(对比ArrayList) 元素的存储结构 在LinkedList中&#xff0c;每一个元素都是Node存储&#xff0c;Node拥有一个存…

取消选中目标CALL

事先在游戏里选中一个怪物bp send,回到游戏里,按ESC&#xff0c;OD断下来,复制 返回到 elementc.072AFDD8 005869B2 返回到 elementc.005869B2 来自 elementc.0058E8A0072AFDEC 00588B1F 返回到 elementc.00588B1F 来自 elementc.00586980072AFE28 005A7346 返回到 el…