HBase – Memstore Flush、StoreFile、File解析

轉載於 https://blog.csdn.net/qq_43733123/article/details/103552467

請多多支持原作者!!!

Memstore

       Memstore 概述

Memstore是HBase框架中非常重要的組成部分之一,是HBase能夠實現高性能隨機讀寫至關重要的一環。深入理解Memstore的工作原理、運行機制以及相關配置,對hbase集羣管理、性能調優都有着非常重要的幫助

HBase中,Region是集羣節點上最小的數據服務單元,用戶數據表由一個或多個Region組成。在Region中每個ColumnFamily的數據組成一個Store。每個Store由一個Memstore和多個HFile組成,如下圖所示:

之前我們提到,HBase是基於LSM-Tree模型的,所有的數據更新插入操作都首先寫入Memstore中(同時會順序寫到日誌HLog中),達到指定大小之後再將這些修改操作批量寫入磁盤,生成一個新的HFile文件,這種設計可以極大地提升HBase的寫入性能;另外,HBase爲了方便按照RowKey進行檢索,要求HFile中數據都按照RowKey進行排序,Memstore數據在flush爲HFile之前會進行一次排序,將數據有序化;還有,根據局部性原理,新寫入的數據會更大概率被讀取,因此HBase在讀取數據的時候首先檢查請求的數據是否在Memstore,寫緩存未命中的話再到讀緩存中查找,讀緩存還未命中纔會到HFile文件中查找,最終返回merged的一個結果給用戶。

可見,Memstore無論是對HBase的寫入性能還是讀取性能都至關重要。其中flush操作又是Memstore最核心的操作,接下來重點針對Memstore的flush操作進行深入地解析:首先分析HBase在哪些場景下會觸發flush,然後結合源代碼分析整個flush的操作流程,最後再重點整理總結和flush相關的配置參數,這些參數對於性能調優、問題定位都非常重要。

           Memstore Flush觸發條件

HBase會在如下幾種情況下觸發flush操作,需要注意的是MemStore的最小flush單元是HRegion而不是單個MemStore。可想而知,如果一個HRegion中Memstore過多,每次flush的開銷必然會很大,因此我們也建議在進行表設計的時候儘量減少ColumnFamily的個數

1.Memstore級別限制:當Region中任意一個MemStore的大小達到了上限(hbase.hregion.memstore.flush.size,默認128MB),會觸發Memstore刷新
2.Region級別限制:當Region中所有Memstore的大小總和達到了上限(hbase.hregion.memstore.block.multiplier * hbase.hregion.memstore.flush.size,默認 2* 128M = 256M),會觸發memstore刷新
3.Region Server級別限制:當一個Region Server中所有Memstore的大小總和達到了上限(hbase.regionserver.global.memstore.upperLimit * hbase_heapsize,默認 40%的JVM內存使用量),會觸發部分Memstore刷新。Flush順序是按照Memstore由大到小執行,先Flush Memstore最大的Region,再執行次大的,直至總體Memstore內存使用量低於閾值(hbase.regionserver.global.memstore.lowerLimit * hbase_heapsize,默認 38%的JVM內存使用量)
4.當一個Region Server中HLog數量達到上限(可通過參數hbase.regionserver.maxlogs配置)時,系統會選取最早的一個 HLog對應的一個或多個Region進行flush
5.HBase定期刷新Memstore:默認週期爲1小時,確保Memstore不會長時間沒有持久化。爲避免所有的MemStore在同一時間都進行flush導致的問題,定期的flush操作有20000左右的隨機延時
6.手動執行flush:用戶可以通過shell命令 flush ‘tablename’或者flush ‘region name’分別對一個表或者一個Region進行flush

           Memstore Flush流程

爲了減少flush過程對讀寫的影響,HBase採用了類似於兩階段提交的方式,將整個flush過程分爲三個階段:

1.prepare階段:遍歷當前Region中的所有Memstore,將Memstore中當前數據集kvset做一個快照snapshot,然後再新建一個新的kvset。後期的所有寫入操作都會寫入新的kvset中,而整個flush階段讀操作會首先分別遍歷kvset和snapshot,如果查找不到再會到HFile中查找。prepare階段需要加一把updateLock對寫請求阻塞,結束之後會釋放該鎖。因爲此階段沒有任何費時操作,因此持鎖時間很短。
2.flush階段:遍歷所有Memstore,將prepare階段生成的snapshot持久化爲臨時文件,臨時文件會統一放到目錄.tmp下。這個過程因爲涉及到磁盤IO操作,因此相對比較耗時。
3.commit階段:遍歷所有的Memstore,將flush階段生成的臨時文件移到指定的ColumnFamily目錄下,針對HFile生成對應的storefile和Reader,把storefile添加到HStore的storefiles列表中,最後再清空prepare階段生成的snapshot

Memstore 總結 

Memstore 中的數據是排序的,當MemStore累計到一定閾值時 就會創建一個新的MemStore,並且將老的MemStore 添加到flush隊列 由單獨的線程flush到磁盤上,稱爲一個StoreFile

StoreFile

       StoreFile簡介

1) 一個Region由多個Store組成,一個Store對應一個ColumnFamily(列族)
Store包括位於內存中的MemStore和位於磁盤的StoreFile;寫操作先寫入MemStore,當Memstore中的數據達到某個閾值,HRegionserver會啓動flashcache進程寫入StoreFile,每次寫入形成單獨的一個StoreFile
2)當StoreFile文件的數量增長到一定閾值後,系統會進行合併(minor、major compaction),在合併過程中會進行版本合併和刪除工作(majar),形成更大的StoreFile
3)當一個Region所有StoreFile的大小和數量超過一定閾值後,會把當前的Region分割爲兩個,並由HMaster分配到相應的HRegionserver服務器,實現負載均衡
4)客戶端檢索數據,先在MemStore找,找不到再找StoreFile

StoreFile以HFile格式保存在HDFS上

1)首先HFile文件是不定長的,長度固定的只有其中的兩塊:Trailer和FileInfo。正如圖中所示的,Trailer中有指針指向其他數據塊的起始點
2)File Info中記錄了文件的一些Meta信息,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等
3)Data Index和Meta Index塊記錄了每個Data塊和Meta塊的起始點
4)Data Block是HBase I/O的基本單元,爲了提高效率,HRegionServer中有基於LRU的Block Cache機制。每個Data塊的大小可以在創建一個Table的時候通過參數指定,大號的Block有利於順序Scan,小號Block利於隨機查詢。 每個Data塊除了開頭的Magic以外就是一個個KeyValue對拼接而成, Magic內容就是一些隨機數字,目的是防止數據損壞
5)HFile裏面的每個KeyValue對就是一個簡單的byte數組。但是這個byte數組裏麪包含了很多項,並且有固定的結構。我們來看看裏面的具體結構:

開始是兩個固定長度的數值,分別表示Key的長度和Value的長度。緊接着是Key,開始是固定長度的數值,表示RowKey的長度,緊接着是 RowKey,然後是固定長度的數值,表示Family的長度,然後是Family,接着是Qualifier(限定符),然後是兩個固定長度的數值,表示Time Stamp和Key Type(Put/Delete)。Value部分沒有這麼複雜的結構,就是純粹的二進制數據了

HFILE結構
解釋1(較爲清晰)

① Data Block 段–保存表中的數據,這部分可以被壓縮
② Meta Block 段 (可選的)–保存用戶自定義的kv對,可以被壓縮
③ File Info 段–Hfile的元信息,不被壓縮,用戶也可以在這一部分添加自己的元信息
④ Data Block Index 段–Data Block的索引。每條索引的key是被索引的block的第一條記錄的key
⑤ Meta Block Index段 (可選的)–Meta Block的索引
⑥ Trailer–這一段是定長的。保存了每一段的偏移量,讀取一個HFile時,會首先 讀取Trailer,Trailer保存了每個段的起始位置(段的Magic Number用來做安全check),然後,DataBlock Index會被讀取到內存中,這樣,當檢索某個key時,不需要掃描整個HFile,而只需從內存中找到key所在的block,通過一次磁盤io將整個 block讀取到內存中,再找到需要的key。DataBlock Index採用LRU機制淘汰
⑦ HFile的Data Block,Meta Block通常採用壓縮方式存儲,壓縮之後可以大大減少網絡IO和磁盤IO,隨之而來的開銷當然是需要花費cpu進行壓縮和解壓縮。
目標Hfile的壓縮支持兩種方式:Gzip,Lzo


解釋2(較爲簡潔明瞭)

① Data(數據塊):保存表中的數據(KeyValue的形式),這部分可以被壓縮。
② Meta (元數據塊):存儲用戶自定義KeyValue
③ File Info:定長;記錄了文件的一些元信息,例如:AVG_KEY_LEN,AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等
④ Data Index(數據塊索引):記錄了每個Data塊的起始索引
⑤ Meta Index(元數據塊索引):記錄了每個Meta塊的起始索引
⑥ Trailer:定長;用於指向其他數據塊的起始點。 

StoreFile 總結

當一個Store中的StoreFile達到一定的閾值後,就會
進行一次合併(major compact),將對同一個key的修改合併到一起
形成一個大的StoreFile,當StoreFile大小達到一定的閾值後,又會對
StoreFile進行Split,等分成兩個StoreFile

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