本文记录了阅读《深入理解kafka核心设计与实践原理》第5章日志存储的相关知识点和理解总结。
关于消息存储的文件夹布局规则
在学习与理解了topic分区、broker的前提下,我们知道分区会被分配到特定的broker中。这里继续展开说明,分区存储具体表现为topic+partitionID名称的文件夹,如下:
:/bitnami/kafka/data$ ls -al
drwxr-xr-x 2 1001 root 4096 Nov 20 23:51 mgr-created-1-2
drwxr-xr-x 2 1001 root 4096 Nov 20 23:51 mgr-created-1-5
drwxr-xr-x 2 1001 root 4096 Nov 20 23:51 mgr-created-1-8
每个分区文件夹内至少包含这几个文件:
kafka1:/bitnami/kafka/data/mgr-created-1-8$ ls
00000000000000000000.index
00000000000000000000.log
00000000000000000000.timeindex
log文件是消息内容主体文件;
index文件是偏移量索引文件;
timeindex是时间戳索引文件。
这样的三个文件组合称为日志分段(Log Segment),分段文件的名称就是文件内第一条消息的offset;
以上这些概念的逻辑示意图如下:
需要单独说明的是: kafka的数据文件目录可以设置为多个,用于支持多个独立的存储设备,提高IO性能。因此就带来一个问题:当此broker节点分配到新分区时,在哪个数据目录创建呢?答案:在分区数量最少的数据目录中创建,直到各个数据目录的topic+partitonID文件夹数量平衡。
关于2个索引文件
偏移量索引文件:用来建立消息偏移量offset到物理地址之间的映射关系,方便快速定位消息所在的物理文件的位置。
时间戳索引文件:根据时间接戳来查找对应的偏移量信息。找到偏移量需要再次查找偏移量索引文件才能最终找到物理文件位置。
kafka中的索引采用系数索引构造,并不保证每个消息都有索引项,而是写入一定数量的消息时才增加一个索引项。好处就是新增消息的维护成本低、索引文件占用空间少,保证了消息写入性能。
由于偏移量和时间戳都是单调递增的,因此查询时,都是利用二分查找快速定位。
日志文件的清理
kafka提供两种清理策略:日志删除、日志压缩;
关于日志删除策略:
- 基于时间:即超过xx天的日志会被删除。
- 基于大小:当所有log日志总大小超过设定值,就会开始删除最早的日志。
- 基于日志起始偏移量:略
关于日志压缩策略:
- 相当于日志整合,非单纯的压缩,尤其要与消息压缩区分开。
- 细节不在展开。
关于采用磁盘存储与内存存储的说明
kafka依赖于文件系统(也就是磁盘)来存储和缓存消息,而不是内存(不是说不用内存)。此处还澄清了一个迷惑点:即顺序写磁盘的速度并不慢。
而且按照kafka的设计,消息写入是顺序的,即追加到最后的段文件中,属于典型的磁盘顺序写入。
借助于现代操作系统的页缓存技术,充分利用内存空间,减少了直接的磁盘IO,更保证了磁盘读写的性能。
关于零拷贝Zero-Copy
零拷贝的含义是数据直接从磁盘复制到网卡设备,不需要经过应用程序处理。由此处说明可知,零拷贝主要应用于磁盘到网卡的转发场景,而不是针对kafka特有。采用零拷贝也只是因为kafka主要依赖磁盘的原因。
综述
关于磁盘这一章节,讲解了kafka自身的分区格式、索引、清理等功能机制。同时也从底层原理方面解释了kafka依赖磁盘但依然保障高性能的原因。