大資料技術-HBase:MSLAB介紹
隨著記憶體資源價格的降低,伺服器的記憶體越來越大,很多都是達到96GB的。而HBase的RS又是記憶體耗用性的,很多時候我們為其分配了比較大的記憶體空間。但與此同時,很多人都會遇到配置大記憶體所導致的各種問題。
首先,我們知道HBase工作依賴於Zookeeper,RS會定期向Master進行狀態彙報,如果長時間沒有收到RS的彙報資訊,Master會認為RS已經死掉,然後開始進行恢復操作。而Zookeeper與RS的會話也可能因為STW的GC導致會話超時,自己便會退出。
其次,很大堆記憶體一旦觸發full gc,除了可能導致長時間的停頓,客戶端感覺到明顯的延遲甚至timeout,另外一個比較嚴重的是隨著時間推移,堆記憶體中存在大量記憶體碎片,帶來的結果是雖然還有很多空餘記憶體,但很多是比較小無法分配使用的,promotion failure。
生產環境一般新生代使用ParNew, 老年代用CMS,觸發儘量別配置太大比例,否則容易產生晉升失敗。
HBase提供了以下幾個引數便於利用上一種機制,防止堆中產生過多碎片,大概思路也是參考TLAB,叫做MSLAB,MemStore-Local Allocation Buffer,為memstore劃分相應的區塊MemStoreLAB,裡面一個位元組陣列固定的大小(curChunk),用於存放KeyValue的具體數值,還有一個變數用於記錄目前空餘空間偏移指標,當一個Chunk被填滿,重新開闢一個位元組陣列空間。有效減少了因為記憶體碎片導致的full gc。
MSLAB,全稱是 MemStore-Local Allocation Buffer,是Cloudera在HBase 0.90.1時提交的一個patch裡包含的特性。它基於Arena Allocation解決了HBase因Region flush導致的記憶體碎片問題。
MSLAB的實現原理(對照Arena Allocation,HBase實現細節):
MemstoreLAB為Memstore提供Allocator。
建立一個2M(預設)的Chunk陣列和一個chunk偏移量,預設值為0。
當Memstore有新的KeyValue被插入時,通過KeyValue.getBuffer()取得data bytes陣列。將data複製到Chunk陣列起始位置為chunk偏移量處,並增加偏移量=偏移量+data.length。
當一個chunk滿了以後,再建立一個chunk。
所有操作lock free,基於CMS原語。
優勢:
KeyValue原始資料在minor gc時被銷燬。
資料存放在2m大小的chunk中,chunk歸屬於memstore。
flush時,只需要釋放多個2m的chunks,chunk未滿也強制釋放,從而為Heap騰出了多個2M大小的記憶體區間,減少碎片密集程度。
開啟MSLAB
hbase.hregion.memstore.mslab.enabled=true // 開啟MSALB
hbase.hregion.memstore.mslab.chunksize=2m // chunk的大小,越大記憶體連續性越好,但記憶體平均利用率會降低
hbase.hregion.memstore.mslab.max.allocation=256K // 通過MSLAB分配的物件不能超過256K,否則直接在Heap上分配,256K夠大了
參考:
http://blog.cloudera.com/blog/2011/02/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-1/
http://blog.cloudera.com/blog/2011/02/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-2/
http://blog.cloudera.com/blog/2011/03/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-3/