本文次要有两大块内容:
- patition 里的 segment file
- 如何查找一条音讯
先看下几个根本的概念:
- partition:topic 物理上的分组,一个 topic 下能够有多个 partition,每个 partion 是有序的
- segment: 每个 patition 由多个 segment file 组成
- offset:partition 中的每个音讯都有一个间断的序列号叫做 offset,用于标识惟一一条 partition 里的音讯
- message:kafka 中最小的存储单位,a commit log.
kafka 的 message 是以 topic 为根本单位,不同的 topic 之间的互相独立的,每个 topic 又能够分为几个不同的 partition,每个 partition 存储一部分 message。
patition 里的 segment file
partition 里的 segment file 是以文件夹的模式存储在 Broker 上的,它们大小相等(具体大小能够通过 config/server.properties 中进行设置)。
segment file 的特点
- 组成。由两局部组成,别离是 index file 与 data file,这两个文件一一对应,后缀别离为.index 与.log
- 命名。partition 的第一个 segment 从 0 开始,后续每个 segment 文件名为上一个 segment 文件最初一条音讯的 offset,20 位数字字符长度,有余用 0 填充。
index file 与 data file 的关系
先看一张图
索引文件中存储着元数据,数据文件存储着音讯,依据索引文件中的元数据咱们能够疾速定位到数据文件里相应的音讯。以索引文件中的 3,497 为例,3 指的是在数据文件中的第 3 个 segment,它是一个逻辑地址;而 497 指的是该音讯在 segment 里的物理偏移地址为 497。
从上图咱们还能够晓得在 00000000000000368769.log 文件里的 Message368772 这个 segment 在全局 partition 示意第 368772 个 message,也就是通过文件名咱们就能够晓得它所在的全局 offset。
data file 物理构造
在图里咱们能够分明地晓得 data file 里记录着音讯的大小 (size) 与具体内容 (payload) 等信息
如何查找一条音讯
partition 的音讯文件为什么要别离生成 index file 与 data file 这两个文件呢?很大一部分起因就是为了不便音讯的查找。这里也能看出 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 了。
通过 offset 查找 message
假如咱们想读取 offset=368776 的 message(参考第图二)
- 查找 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.index 这个文件是 partition 里的第几个文件)和 00000000000000368769.log 的物理偏移地址(依据索引文件里的物理偏移量),而后再通过 00000000000000368769.log 程序查找直到 offset=368776 为止。
segment index file 并没有为数据文件中的每条 message 建设索引,而是采取稠密索引存储形式,每隔肯定字节的数据建设一条索引,它缩小了索引文件大小,通过 map 能够间接内存操作,稠密索引为数据文件的每个对应 message 设置一个元数据指针, 它比浓密索引节俭了更多的存储空间