【前言】
我们都知道日志聚合后的文件是存放在HDFS中的,然而每个application可能会有很多的container,每个container又有多个日志文件,那么日志聚合后,这些日志文件在HDFS中是怎样进行存放的。本文就来聊聊hadoop日志聚合后的文件格式及相关内容。
【TFile&BCFile】
在HDFS中,提供了多种文件格式,有普通的文件文件格式和二进制格式;用于KV键值对存储的SequenceFile,TFile;有用于列式存储的parquet,rc,orc等格式。
这里重点要说的是TFile,因为聚合后的日志文件就是采用这种格式进行存储的。
提到TFile,那么就不得不提起BCFile,因为BCFile是TFile的底层物理存储层。
BCFile是Block Compresed File的缩写,顾名思义,数据的存储是按照一个一个的Block进行存储的,同时这些block是可以进行压缩存储的。按照作用这些block可以分为数据块(DataBlock)和元数据块(MetaBlock),数据块通常就是要写入的数据内容,而元数据块可以自定义写入,BCFile也会将数据块的索引信息记录下来作为元数据块写入到文件中。
BCFile的具体格式如下图所示:
了解了BCFile后,再来看TFile的格式。TFile本身是一堆KV的容器,Key和Value均为无类型的字节数据,其中Key的长度限制为64KB,而Value的长度则没有限制。
尽管TFile保存的是KV键值对,但底层采用的是BCFile,所以实际上就是将不同的KV存放在不同的数据块中(注:一个KV只会存在于一个数据块中,不会出现Key存放在一个block中,value存放到另外一个block的情况,也不会出现一个value跨block存放的情况)
另外,TFile还定义了两个元数据块,一个叫TFile.meta,记录了TFile的版本号信息、TFile中KV键值对的总数、以及用于对Key进行排序的排序算法名;另外一个元数据块叫TFile.index,记录了TFile中第一个Key的长度及名称,每个数据块中最后一个Key的名称、以及每个数据块中KV键值对的个数。
具体格式如下图所示:
注:KV键值对在写入的时候,有几个小细节
【日志聚合的文件格式】
有了前面的铺垫,再来看看日志聚合的文件是怎么在TFile中存储的。
由于TFile本质上是KV键值对的容器,因此可以变相理解为日志聚合后的文件中包含了哪些KV键值对,具体存储的KV包括:
【实际文件分析】
下面就以一个实际的文件按照上面的说明对照进行分析下。
有几个需要注意的地方:
【总结】
本文总结了日志聚合文件的格式。从格式中可以看到,TFile的元数据信息结合BCFile中的数据块索引信息就可以知道每个数据块的第一个key和最后一个key的偏移位置,这样可以快速的从前或从后进行遍历查找。另外,不难猜到,文件的读取是从尾部开始,先读取元数据块索引文件的偏移位置信息,然后移动到该位置读取元数据块索引的信息,进而得到数据块索引的偏移位置,再移动到该位置读取数据块索引信息,得到每个数据块的偏移位置,数据块中的kv个数等。实际上下载某个container的日志文件时,确实也是按照该方式进行的。有兴趣的可以阅读相关源码。