HFile V2介紹[0.92到0.98之前的版本]

     hbase 0.92版本中,爲了改進在大數據存儲下的效率,HFile做了改變。HFile V1的主要問題是,你需要加載(load)所有的單片索引和BloomFilter到內存中,這會導致每臺服務器有數GB的內存被塊索引消耗掉,這對域服務器的可擴展性和性能有顯著的負面影響。此外,由於直到加載完所有塊索引數據之後,才能認爲域啓動完成,因此這樣的塊索引大小會明顯地拖慢域的啓動速度。 爲了解決這個問題,v2引入了多級索引[一個根索引塊和多個葉塊,只有根索引(索引數據塊)必須一直保存在內存中,葉索引以塊的級別存儲,這意味着它是否在內存中出現取決於塊是否在內存中出現。葉索引僅在加載塊時被加載到內存中,並且在塊移出時被移出內存。此外,葉級別索引的結構化方式允許在不進行反序列化的情況下,對鍵進行二叉搜索]和分塊BloomFilterHFile v2改進了速度,內存和緩存利用率。

 HFile V2的文件存儲格式如下圖:

 

HFile的組成分成四部分,分別是Scanned Block(數據block)、Non-Scanned block(元數據block)、Load-on-open(在hbase運行時,HFile需要加載到內存中的索引、bloom filter和文件信息)以及trailer(文件尾)

HFile V2中根據key查找數據的過程如下:

1)先在內存中對HFile的root索引進行二分查找,如果支持多級索引,則定位到leaf index/intermediate index,如果是單級索引,則定位到數據塊data block;

2)如果支持多級索引,則會從cache/hdfs中讀取leaf/intermediate index chunk,在leaf/intermediate chunk根據key值進行二分查找(leaf/intermediate index chunk支持二分查找),找到對應的data block。

3)從cache/hdfs中讀取數據塊;

4)在數據塊中遍歷查找對應的數據。

DataBlock

DataBlock是用於存儲具體kv數據的block,相對於索引和meta(這裏的meta是指bloom filter)DataBlock的格式比較簡單。

在DataBlock中,KeyValue的分佈如下圖,在KeyValue後面跟一個timestamp。

   

HFileIndex

     

HFile中的index level是不固定的,根據不同的數據類型和數據大小有不同的選擇.

      主要有兩類,一類是single-level(單級索引),另一類是multi-level(多級索引,索引block無法在內存中存放,所以採用多級索引)。具體見

HFileBlockIndex類

[Writes the block index into the output stream. Generate the tree from bottom up. The leaf level is written to disk as a sequence of inline blocks, if it is larger than a certain number of bytes. If the leaf level is not large enough, we write all entries to the root level instead. After all leaf blocks have been written, we end up with an index referencing the resulting leaf index blocks. If that index is larger than the allowed root index size, the writer will break it up into reasonable-size intermediate-level index block chunks write those chunks out, and create another index referencing those chunks. This will be repeated until the remaining index is small enough to become the root index. However, in most practical cases we will only have leaf-level blocks and the root index, or just the root index.]

HFile中的index chunk有兩大類,分別是root index chunknonRoot index chunk。  

                 nonRoot index chunk又分爲interMetadiate index chunkleaf index chunk,但intermetadiate index chunk和leaf index                chunk在內存中的分佈是一樣的。

               對於meta block和bloom block,採用的索引是single-level形式,採用single-level時,只用root index chunk來保存指向block的索引信息(root_index-->xxx_block)。

                對於數據規模決定是否寫入 leaf index和bloom block。

                 a、一開始的時候,HFile的data block數量較少時,採用的是single level(root_index-->data_block),索引的searchTreeLevel=2

                 b、當data block數量較多時,採用的是multi-level。

                 root Index越來越大,隨之所耗內存增大,會以多層結構存儲數據索引,使用root index chunk和leaf index chunk來保存索引信息(root_index-->leaf_index-->data_block),索引的searchTreeLevel=2

                  但當data block數量很多時,root index 再內存無法存放的時候,就變成三級索引,使用root index chunk、intermetadiate index chunk和leaf index chunk來保存指向數據的索引

             (root_index-->intermediate_index-->leaf_index-->data_block),索引的searchTreeLevel=3

                 

Fileds for midKey:
          這部分數據是Optional的,保存了一些midKey信息,可以快速地定位到midKey,常常在HFileSplit的時候非常有用。

MetaIndex:
           即meta的索引數據,和data index類似,但是meta存放的是BloomFilter的信息

FileInfo:

           保存了一些文件的信息,如lastKey,avgKeylen,avgValueLen等等,一會我們將會寫程序將這部分內容解析出來並打印看看是什麼東西。同樣,FileInfo使用了Protobuf來進行序列化。

Bloom filter metadata:

            分爲GENERAL_BLOOM_META[key是否存儲在hbase]及DELETE_FAMILY_BLOOM_META[確定key是否已經被刪除]二種

   clip_image032

      

Bloom meta index在磁盤中的格式如上圖所示。

Version:表示版本;

totalByteSize:表示bloom filter的位組的bit數。

HashCount:表示一個key在位組中用幾個bit位來進行定位。

HashType:表示hash函數的類型。

totalKeyCount:表示bloom filter當前已經包含的key的數目.

totalKeyMaxs:表示bloom filter當前最多包含的key的數目.

numChunks:表示bloom filter中包含的bloom filter block的數目.

comparatorName:表示比較器的名字.

HFile 詳解圖: 

 


發佈了31 篇原創文章 · 獲贊 24 · 訪問量 72萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章