HMaster 沒有處理過重的負載,並且實際的數據服務不經過 HMaster,它的主要任務有2個:一、管理Hbase Table的 DDL操作, 二、region的分配工作,任務不是很艱巨。
但是如果采用默認自動split region的方式,HMaster會稍微忙一些,負載不大,可適度對此進程做適量放大heap 的操作,但不可太大。
RegionServer在寫入數據時,數據會先保存在memstore 中,當大於閾值時候,再寫入到磁盤。因為寫入的數據是由客戶端在不同時間寫入的,故而他們占據的Java堆空間很可能是不連續的,會出現孔洞,所以需要調整垃圾回收機制。
RegionServer的新生代大小在128M~512M,老生代大小在幾GB。最初寫入的數據會保存在新生代,再刷寫到磁盤;當數據刷寫到磁盤的速度較慢時候,新生代中的數據停留時間過長,會被移到老生代。
新生代空間可以被迅速回收,對內存管理沒有影響;老生代數據量大,回收慢,對內存管理影響大。所以二者需要不同的垃圾回收策略。
JVM設置
進入conf目錄,修改hbase-env.sh文件
vi hbase-env.sh
修改HBASE_OPTS屬性值:
$HBASE_OPTS -Xmx3g -Xms3g -Xmn512m -Xss256k -XX:MaxPermSize=256m -XX:SurvivorRatio=2 -XX:MaxTenuringThreshold=15 -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+UseCMSInitiatingOccupancyOnly -XX:-DisableExplicitGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintTenuringDistribution -Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log
配置解讀:
-Xmx3g 最大堆內存3g
-Xms3g 初始堆內存設置與最大堆內存一樣大。如果Xms設置得比較小,當遇到數據量較大時候,堆內存會迅速增長,當上升到最大又會回落,伸縮堆大小會帶來壓力。
-Xmn512M 新生代512M。新生代不能過小,否則新生代中的生存周期較長的數據會過早移到老生代,引起老生代產生大量內存碎片;新生代也不能過大,否則回收新生代也會造成太長的時間停頓,影響性能。
-XX:CMSInitiatingOccupancyFraction=75 初始占用比為75%的時候開始CMS回收。此值不能太小,否則CMS發生得太頻繁。此值不能太大,否則因為CMS需要額外堆內存,會發生堆內存空間不足,導致CMS 失敗。
-Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log 寫入日志
-XX:+UseParNewGC
新生代采用 ParallelGC 回收器。ParallelGC 將停止運行Java 進程去清空新生代堆,因為新生代很小,所以停頓的時間也很短,需幾百毫秒。
-XX:+UseConMarkSweepGC
老年代采用CMS回收器(Concurrent Mark-Sweep Collector) . CMS 在不停止運行Java進程的情況下異步地完成垃圾回收,CMS會增加CPU的負載,但是可以避免重寫老年代堆碎片時候的停頓。老年代回收不可使用 ParallelGC 回收 機制,因為老生代的堆空間大,ParallelGC會造成Java進程長時間停頓,使得RegionServer與ZooKeeper的會話超時,該RegionServer會被誤認為已經奔潰並會被拋棄。
對於老年代來說, 它可以更早的開始回收。當分配在老年代的空間比率超過了一個閥值,CMS 開始運行。如果 CMS 開始的太晚,HBase 或許會直接進行 full garbage collection。這種情況會導致block所有的線程,如果這個時間過長,就會導致hbase連接超時,結果就是regionserver集體下線。這是不能容忍額。為了避免這種情況的發生,我們建議設置 -XX:CMSInitiatingOccupancyFraction JVM 參數來精確指定在多少百分比 CMS 應該被開始,正如上面的配置中做的那樣。在 百分之 60 或 70 開始是一個好的實踐。當老年代使用 CMS,默認的年輕代 GC 將被設置成 Parallel New Collector。
再來看看hbase為什么可能進行full gc,如果我們不配置-XX:CMSInitiatingOccupancyFraction,jdk1.5以后會使用默認值90%,那么很可能,當老年代內存占用超過分配給他的內存大小的90%,會進行CMS(老年代的回收),但是不會阻止年輕代到老年代的遷移,如果遷移過快,CMS較慢,會出現老年代內存使用率100%,這時會導致full gc。如果我們把這個參數調整小一點,那么能給年輕帶到老年代遷移的同時做CMS時一些時間,也就減少了full gc的發生。當然這可能會頻繁的gc,但總比整個hbase掛掉的好不是么?
示例:

Master和RegionServer單獨配置:
export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS $HBASE_JMX_BASE -Xmx2g -Xms2g -Xmn750m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70"
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS $HBASE_JMX_BASE -Xmx20g -Xms20g -Xmn1g -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly"
