主要内容:

  • Kafka底层数据存储设计
  • Kafka查询数据策略
  • 具体demo及原理图

Kafka底层数据存储设计

topic——>partitions——>segments——>.index&.log

  • Kafka中的消息是以topic为基本单位进行组织和分类;

  • 每个topic分为多个partition,partition是以文件的形式存储在文件系统中,由参数log.dir配置。如创建了名为first_topic的topic,共有3个分区,那么在其数据目录中就会自动创建3个目录:first_topic-0first_topic-1first_topic-2。partition命名规范:topic_name+”-“+partition_id

  • 每个partition又被分为多个大小相等的segment,由参数log.segment.bytes配置,默认1GB。Kafka中写入日志的方式是以顺序追加的方式写入的,当日志文件大小达到一定大小就会做切分,形成一个新的日志文件,这里可以把一个一个的日志文件作为一个日志段。日志段的引入方便了Kafka数据的查询(二分查找)与定位。日志段分为活跃日志段和非活跃日志段,只有活跃日志段(当前日志段,一个分区只可能存在一个)可以被写入和读取,非活跃日志段只能被读取;

在这里插入图片描述
  • segment主要由3部分组成:

    • 索引文件:后缀为.index的文件;
    • 日志文件:后缀为.log的文件;
    • 时间戳索引文件:后缀为timeindex的文件。

    segment 文件命名规则:partition 全局的第一个 segment从 0 开始,后续每个 segment 文件名为上一个 segment文件最后一条消息的 offset 值进行递增。数值最大为 64 位long 大小,20 位数字字符长度,没有数字用 0 填充。如:

    第一个 log 文件的最后一个 offset 为:5376,下一个segment 的文件命名为:
    00000000000000005376.log
    00000000000000005376.index
    00000000000000005376.timeindex

Kafka查询数据策略

如果每个partition只有一个数据文件,在数据量较大的情况下查找某个offset对应的数据时,由于是顺序查找,查询效率就很低。那Kafka是如何解决查询效率低的问题呢?

在这里插入图片描述
  • 分段:将数据文件分段,每段放在一个单独的数据文件里,由于文件命名与offset有关,所以在查找指定offset的数据时,使用二分查找法可快速定位到segment;
  • 索引:数据文件分段使得可以在一个较小的数据文件中查找对应offset的数据了,但是这依然需要顺序扫描整个文件。为了进一步提高查找的效率,Kafka为每个分段后的数据文件建立了索引文件。其包含两个部分:
    • 相对offset:这里的相对offset和log文件里的offset不同,相对offset是每个segment都从1开始的,而绝对offset在整个partition中都是唯一的。举例:分段后的一个数据文件的offset是从20开始,那么offset为25的数据在index文件中的相对offset就是25-20 = 5。存储相对offset可以减小索引文件占用的空间
    • position:表示该条数据在数据文件中的绝对位置。只要打开文件并移动文件指针到这个position就可以读取对应的数据了。

index文件中并没有为数据文件中的每条数据建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。但缺点是没有建立索引的数据也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

具体demo及原理图

在这里插入图片描述