一、問題分析
核心:HBase是使用Java語言開發的,所以需要依賴于JVM,
HBase的MemStore本質上是一塊快取,這就會面臨Java的GC問題,在資料寫入MemStore時,寫入資料會產生記憶體碎片,并且RegionServer由多個Region組成,每一個Region根據列簇的個數多少具有相同數量的MemStore,MemStore的資料會混合在一起寫入堆記憶體中(堆記憶體是共享的),
二、程序分析
- 上圖中不同顏色方塊表示4個Region
- 白色方塊為可分配空間
當Region3執行flush操作將資料落入磁盤,藍色區域被釋放,為后續資料的寫入分配空間,分配時會生成更小的記憶體空間,隨著MemStore中的資料不斷寫入和flush,JVM會產生大量的記憶體碎片,導致最后無法給物件分配足夠的空間,這時會觸發Full GC來合并記憶體碎片,
三、優化:MSLAB
HBase使用了一種GC優化的技術,可以有效地減少Full GC的頻率——MSLAB
- 每一個MemStore實體化得到一個MemStoreLAB實體
- MemStoreLAB申請一個2M的Chunk陣列,維護一個偏移量Offset=0
- 每次一個Key-Value資料插入MemStore后,MemStoreLAB將這個資料轉化成陣列,復制到Chunk陣列中,Offset隨之增長
- Chunk滿了后,再申請一個新的2M的Chunk陣列,
優化點:此時如果進行flush操作,產生的記憶體碎片的粒度變粗(因為我flush釋放掉的都是2M的Chunk陣列,釋放記憶體新產生的碎片也將大于等于2M)
四、深度優化:MemStoreChunkPool
MSLAB優化后,還存在一些問題,當Chunk陣列寫滿后,會再申請一個Chunk陣列,多次的申請會在新生代觸發YongGC,可以對這種情況進行優化,將Chunk陣列進行復用,
-
創建一個ChunkPool來管理未被參考的Chunk陣列(這樣不會被垃圾回收)
-
當Chunk陣列不存在參考,放回Pool中
-
當ChunkPool達到最大容量,不再接受新的Chunk陣列
-
如果需要Chunk陣列,先去Pool中查看是否有可用的Chunk,沒有則申請新Chunk陣列
-
感覺有用的話,點個贊鼓勵一下~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/385524.html
標籤:其他
