Hfile分為4部分,其中loadOnOpen section 和trailer這2部分是open file時就會加載到記憶體的。

Step1:
讀取檔案末尾的4Bytes,得到Hfile format版本号,進而知道Trailer部分的大小, v2和v3都固定為4096Bytes;
Step2:
讀取檔案末尾的4096Bytes,這部分整體作為一個block,包含一些重要的中繼資料資訊,目前有15個,分為以下幾類;
偏移量:loadOnOpenDataOffset、fileinfoOffset、firstDataBlockOffset、lastDataBlockOffset;
數量和大小:totalUncomressedBytes、entryCount、dataIndexCount、metaIndexCount、uncompressedDataIndexSize、numDataIndexLevels
算法:compressionCodec、comparatorClassName、encryptionKey
版本号:majorVersion、minorVersion
其中,fileinfoOffset在v2以後已經沒有實際用途
示例:
fileinfoOffset=1231091280,
loadOnOpenDataOffset=1231084052,
dataIndexCount=143,
metaIndexCount=0,
totalUncomressedBytes=4052639474,
entryCount=44722287,
compressionCodec=SNAPPY,
uncompressedDataIndexSize=18657365,
numDataIndexLevels=2,
firstDataBlockOffset=0,
lastDataBlockOffset=1231031083,
comparatorClassName=org.apache.hadoop.hbase.CellComparatorImpl,
encryptionKey=NONE,
majorVersion=3,
minorVersion=3
Step3:
根據loadOnOpenDataOffset讀取Root Data Index block,包含numEntries和具體entry資料,每個entry包含offset、dataSize和key;
這裡entry所表示的block類型與檔案大小有關:
如果檔案較小,Trailer中numDataIndexLevels字段的值為1,entry表示的是dataBlock,
如果檔案較大,Trailer中numDataIndexLevels字段的值為2,entry表示的是leafIndexBlock
如果檔案很大,Trailer中numDataIndexLevels字段的值為3,entry表示的是IntermediaLevelIndexBlock
較大和很大的門檻值分别大約為100M和100G,該門檻值與key長度和block大小相關;
讀取分為2步:先讀header(固定33位元組),再根據header裡面onDiskSizeWithoutHeader的值讀取data部分;
這裡在讀取data時有個優化,會額外多讀取一個header大小的資料,目的是使下一個block的讀取可以一步完成,減少一次io互動,後續幾個block的讀取都是如此;
另外,該block末尾還存儲了幾個值,用于split時快速找到splitPoint:midLeafBlockOffset、midLeafBlockOnDiskSize、midKeyEntry;
Step4:
讀取FileInfo該block以鍵值對的方式存儲了一些中繼資料,讀取之後記憶體中以Map形式存在,作為對比,Trailer内部隻存儲值,以位置順序區分不同屬性;
另外,這部分沒有大小限制,可以根據需要靈活擴充,目前版本存儲的屬性示例如下;
BLOOM_FILTER_TYPE = ROW
DELETE_FAMILY_COUNT = 0
EARLIEST_PUT_TS = 1479619233886
KEY_VALUE_VERSION = 1
LAST_BLOOM_KEY = 69993111f5d1dfa4179d9f278192a0ad
MAJOR_COMPACTION_KEY = true
MAX_MEMSTORE_TS_KEY = 15986682
MAX_SEQ_ID_KEY = 15986682
TIMERANGE = 1479619233886....1577672100675
hfile.AVG_KEY_LEN = 73
hfile.AVG_VALUE_LEN = 5
hfile.CREATE_TIME_TS = 1577728182220
hfile.LASTKEY = 69993111f5d1dfa4179d9f278192a0ad/tag:userkn_zhengxin_list/1575836971202/Put/vlen=0/mvcc=0
Step5:
讀取General BloomFilter Meta And Index
BloomFilter block的index固定隻有一層,結構與RootDataIndex 類似;
meta部分額外包含了幾個與bloom相關的算法和統計資訊:totalByteSize、hashCount、hashType、totalKeyCount、totalMaxKeys;
Step6:
讀取DeteleFamily BloomFilter Meta And Index
該block結構與General BloomFilter一緻;