kafka存储机制

来源:互联网 发布:拓扑发现 泛洪算法 编辑:程序博客网 时间:2024/05/17 00:16
转载自:http://blog.csdn.net/lujinhong2/article/details/47421823
              http://blog.csdn.net/jewes/article/details/42970799

       Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的。每个topic又可以分成几个不同的partition,每个partition存储一部分Message。
       Partition是以文件的形式存储在文件系统中,比如,创建了一个名为test的topic,其有5个partition,那么在Kafka的数据目录中(由配置文件中的log.dirs指定的)中就会有这样5个目录: test-0,test-1,test-2,test-3,test-4,其命名规则为<topic_name>-<partition_id>,里面存储的分别就是这5个partition的数据。
       Partition中的每条Message由offset来表示它在这个partition中的偏移量,这个offset不是该Message在partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了partition中的一条Message。因此,可以认为offset是partition中Message的id。
       Kafka解决查询效率的手段之一是将数据文件划分为多个segment,比如有100条Message,它们的offset是从0到99。假设将数据文件分成5段,第一段为0-19,第二段为20-39,以此类推,每段放在一个单独的数据文件里面,数据文件以该段中最小的offset命名。这样在查找指定offset的Message的时候,用二分查找就可以定位到该Message在哪个段中。
       发到某个topic的消息会被均匀的分布到多个partition上,broker收到发布消息往对应partition的最后一个segment上添加该消息,当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到,segment达到一定的大小后将不会再往该segment写数据,broker会创建新的segment。
       数据文件分段使得可以在一个较小的数据文件中查找对应offset的Message了,但是这依然需要顺序扫描才能找到对应offset的Message。为了进一步提高查找的效率,Kafka为每个分段后的数据文件建立了索引文件,文件名与数据文件分段的名字是一样的,只是文件扩展名为.index。索引文件中包含若干个索引条目,每个条目表示数据文件中一条Message的索引。索引包含两个部分,分别为相对offset和position。

       下面以几张图来描述一下Message是如何在Kafka中存储的,以及如何查找指定offset的Message的。比如:有5个partition的名为为page_visits的topic的目录结构为:
       
        每个partition是分段的,每个段叫LogSegment,包括了一个数据文件和一个索引文件,下图是某个partition目录下的文件:
       
       可以看到,这个partition有4个LogSegment。


       
       从上图中可以看出,索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。以索引文件中元数据3,497为例,依次在数据文件中表示第3个message(在全局partiton表示第368772个message)、以及该消息的物理偏移地址为497。
       例如读取offset=368776的message,需要通过下面2个步骤查找。
       第一步查找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,通过第一步定位到的00000000000000368769.index,368776-368769=7,表示在索引文件中第7个message,于是定位到了6,1407记录,之后在00000000000000368769.log中找到1407物理偏移地址的message是Message368775,然后顺利查找直到offset=368776为止。
       这样做的优点,index文件中不用为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

总结一下Kafka高效文件存储设计特点:
       • Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
       • 通过索引信息可以快速定位message和确定response的最大大小。
       • 通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
       • 通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。
0 0
原创粉丝点击