天天看點

Hbase 學習(五) 調優

當我們往hbase寫入資料,它首先寫入memstore當中,當menstore的值大于hbase.hregion.memstore.flush.size參數中設定的值後,就會寫入硬碟。

在hbase-env.sh檔案中,我們可以設定hbase_opts或者hbase_regionserver_opts,後者隻影響region server程序。

《hbase權威指南》推薦了上述的寫法,下面是從網上搜的,原書中為什麼要這麼設定的解釋真心看不懂。

-xmx8g -xms8g –xmn128m :最大堆記憶體8g,最小堆記憶體8g,新生代記憶體-xmn128m。

-xx:+useparnewgc : 設定對于新生代的垃圾回收器類型,這種類型是會停止java程序,然後再進行回收的,但由于新生代體積比較小,持續時間通常隻有幾毫秒,是以可以接受。

-xx:+useconcmarksweepgc :設定老生代的垃圾回收類型,如果用新生代的那個會不合适,即會導緻java程序停止的時間太長,用這種不會停止java程序,而是在java程序運作的同時,并行的進行回收。

-xx:cmsinitiatingoccupancyfraction :設定cms回收器運作的頻率,避免前兩個參數引起java程序長時間停止,設定了這個之後,不需要停止java程序,但是會提高cpu使用率。

最後兩句是輸出詳細的日志。

memstore-local allocation buffer,是cloudera在hbase 0.90.1時送出的一個patch裡包含的特性。它基于arena allocation解決了hbase因region flush導緻的記憶體碎片問題。

<b>mslab的實作原理</b>(對照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原語。

<b>優勢:</b>

keyvalue原始資料在minor gc時被銷毀。

資料存放在2m大小的chunk中,chunk歸屬于memstore。

flush時,隻需要釋放多個2m的chunks,chunk未滿也強制釋放,進而為heap騰出了多個2m大小的記憶體區間,減少碎片密集程度。

<b>開啟mslab</b>

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夠大了。

直接上圖吧,說多了沒用。

Hbase 學習(五) 調優

推薦使用snappy,性能最好,但是snappy要單獨安裝,安裝教程等我裝成功了,再發一個文檔出來吧。

對于實時性要求穩定的系統來說,不定時的split和compact會使叢集的響應時間出現比較大的波動,是以建議把split和compact關閉,手動進行操作,比如我們把hbase.hregion.max.filesize設定成100g(major compaction大概需要一小時,設定太大了,compaction會需要更多的時間),major compaction是必須要做的,群裡有個網友給資料設定了過期時間,資料被邏輯删除了,但是沒有釋放硬碟空間,why?沒有進行major compaction,最後是手動進行的合并。

在我們設計rowkey的時候,在前面加上随機數,比如0rowkey-1,1rowkey-2,0rowkey-3,1rowkey-4,去前面加上個随機數,就會有負載均衡的效果,但是如果這樣做了,某個機器的資料還是比别的機器要多很多,這個怎麼辦呢?我們可以手動調用move()方法,通過shell或者hbaseadmin類,或者調用unassign()方法,資料就會轉移了。