Kafka的消息在broker上都是以log的形式进行储存管理的,本篇主要介绍log的管理,包括log结构、建立、读写、分段、清理等。html
Kafka中的Message是以topic为基本单位组织的,不一样的topic之间是相互独立的。每一个partition存储一部分Message。引用官方的一张图,能够直观地看到topic和partition的关系。git
Partition中的每条Message由offset来表示它在这个partition中的偏移量,这个offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它惟一肯定了partition中的一条Message。所以,能够认为offset是partition中Message的id。partition中的每条Message包含了如下三个属性:github
有多大,data为message的具体内容。数据库
在v0版本中,kafka的消息格式以下图所示:segmentfault
在V1版本中,kakfa的消息格式以下图所示:服务器
V2版本并发
具体能够参考下文app
http://www.uml.org.cn/bigdata/2018051731.asp性能
数据文件的分段.net
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 log dir下的文件分布:
1)一个Partition Log 对应于一个kafka broker 的log dir下面的一个分区目录。
2)一个LogSegment对应了partition log directoy下的两个文件:一个.log文件,一个.index文件。
在一个broker上的log都是经过LogManger来管理的,Kafka 的日志管理(LogManager)主要的做用是负责日志的建立、检索、清理,日志相关的读写操做其实是由日志实例对象(Log)来处理的。
LogManager 线程是在节点的 Kafka 服务启动时启动的,相关代码以下:
初始化 LogManger 主要有两个步骤:
虽然使用的是线程池提交任务,并发进行 load 分区日志,但这个任务自己是阻塞式的,只有当全部的分区日志加载完成,才能调用 startup() 启动 LogManager 线程。
KafkaServer 调用 startup()
方法启动 LogManager 线程,LogManager 启动后,后台会运行四个定时任务,代码实现以下:
四个后台定时线程的做用:
第一种:delete,即若是LogSegment到期了删除之,或者LogSegment+此次要添加的消息 > LogSegment的最大容量则删除最老的的LogSegment
第二种:compact,进行log压缩,也能够有效减小日志文件文件大小,缓解磁盘紧张状况。
在有些场景中,key和对应的value的值是不断变化的,就像数据库的记录同样,能够对同一条记录进行修改,在kafka中表现就是在某一时刻key=value1,可能在后续某一时刻,添加了一个key=value2的消息,若是消费者只关心最新的值,那么日志压缩就显得颇有用,以下图所示:
clean: 表示已经压缩的部分,压缩以后,offset是断断续续的,不是增量递增的
dirty: 表示未压缩部分,offset依然是连续递增的
https://www.codetd.com/article/1652292
http://www.javashuo.com/article/p-goagrlby-bo.html
https://blog.csdn.net/zhanglh046/article/details/72821483
https://blog.csdn.net/wl044090432/article/details/51008093
http://www.javashuo.com/article/p-wvionlqd-b.html
http://www.uml.org.cn/bigdata/2018051731.asp
http://www.javashuo.com/article/p-cafkmorp-cc.html
---------------------
做者:happy19870612
来源:CSDN
原文:https://blog.csdn.net/zhanglh046/article/details/72821483