1.6.1 Segment
Last updated
Last updated
首先回顾一下之前讲到的基本结构:
可以看到,Kafka 的数据存储是以副本为单位的日志存储。也就是说,我们之前讲到的 Topic / Partition / Replica 等等都是逻辑上的概念,真正落实到物理存盘上的最终还是日志。
日志结构示意图:
简单来说,每一个分区对应物理意义上的一个文件夹,其中又包含了许许多多的Segment,每一个Segment又对应各自的物理文件。
以我电脑上生成的日志文件举例:
此时一个很自然的疑问是:我们都以及将一个Topic细分成不同的分区了,为什么还要引入Segment呢?
这里给出三个可能的原因:
避免单个文件过大(考虑到Kafka面对的数据量)
方便删除,支持顺序读写
保证顺序读写是 Kafka 日志设计中很重要的部分。为了实现这一点,Consumer通过 Offset 顺序消费数据,而不删除已经消费的数据,避免了随机写磁盘的过程。 当kafka决定要删除旧数据时,直接删除segment对应物理文件,以此保证顺序读写。
就我的理解而言,一个分区就像是一个巨大的数组,Segment以 Append-Only的形式从数组后方插入,其删除也对应着一个Segment的整段删除,这在最大程度上保证了磁盘的顺序读写。
(PS. 关于磁盘顺序读写的好处:)
增加层次,便于查找,这在之后会讲到。
本身 OS 里的介绍的 LSM 也会用 segment 来吸收多个写操作
总的而言,Segment的设计已经让我们把目光从逻辑概念转到了物理文件落盘的具体实现上,其在分区往下又划分出了一个新的层次对应,是LSM的基本组成部分。