hbase調優


http://blog.csdn.net/rzhzhz/article/details/7481674

 

 

官方Book Performance Tuning部分章節沒有按配置項進行索引,不能達到快速查閱的效果。所以我以配置項驅動,重新整理了原文,並補充一些自己的理解,如有錯誤,歡迎指正。

配置優化

zookeeper.session.timeout
默認值
:3分鐘(180000ms)
說明:RegionServer與Zookeeper間的連接超時時間。當超時時間到後,ReigonServer會被Zookeeper從RS集羣清單中移除,HMaster收到移除通知後,會對這臺server負責的regions重新balance,讓其他存活的RegionServer接管.
調優
這個timeout決定了RegionServer是否能夠及時的failover。設置成1分鐘或更低,可以減少因等待超時而被延長的failover時間。
不過需要注意的是,對於一些Online應用,RegionServer從宕機到恢復時間本身就很短的(網絡閃斷,crash等故障,運維可快速介入),如果調低timeout時間,反而會得不償失。因爲當ReigonServer被正式從RS集羣中移除時,HMaster就開始做balance了(讓其他RS根據故障機器記錄的WAL日誌進行恢復)。當故障的RS在人工介入恢復後,這個balance動作是毫無意義的,反而會使負載不均勻,給RS帶來更多負擔。特別是那些固定分配regions的場景。

 

hbase.regionserver.handler.count
默認值
:10
說明:RegionServer的請求處理IO線程數。
調優
這個參數的調優與內存息息相關。
較少的IO線程,適用於處理單次請求內存消耗較高的Big PUT場景(大容量單次PUT或設置了較大cache的scan,均屬於Big PUT)或ReigonServer的內存比較緊張的場景。
較多的IO線程,適用於單次請求內存消耗低,TPS要求非常高的場景。設置該值的時候,以監控內存爲主要參考。
這裏需要注意的是如果server的region數量很少,大量的請求都落在一個region上,因快速充滿memstore觸發flush導致的讀寫鎖會影響全局TPS,不是IO線程數越高越好。
壓測時,開啓
Enabling RPC-level logging,可以同時監控每次請求的內存消耗和GC的狀況,最後通過多次壓測結果來合理調節IO線程數。
這裏是一個案例?
Hadoop and HBase Optimization for Read Intensive Search Applications,作者在SSD的機器上設置IO線程數爲100,僅供參考。

hbase.hregion.max.filesize
默認值
:256M
說明:在當前ReigonServer上單個Reigon的最大存儲空間,單個Region超過該值時,這個Region會被自動split成更小的region。
調優
小region對split和compaction友好,因爲拆分region或compact小region裏的storefile速度很快,內存佔用低。缺點是split和compaction會很頻繁。
特別是數量較多的小region不停地split, compaction,會導致集羣響應時間波動很大,region數量太多不僅給管理上帶來麻煩,甚至會引發一些Hbase的bug。
一般512以下的都算小region。

大region,則不太適合經常split和compaction,因爲做一次compact和split會產生較長時間的停頓,對應用的讀寫性能衝擊非常大。此外,大region意味着較大的storefile,compaction時對內存也是一個挑戰。
當然,大region也有其用武之地。如果你的應用場景中,某個時間點的訪問量較低,那麼在此時做compact和split,既能順利完成split和compaction,又能保證絕大多數時間平穩的讀寫性能。

既然split和compaction如此影響性能,有沒有辦法去掉?
compaction是無法避免的,split倒是可以從自動調整爲手動。
只要通過將這個參數值調大到某個很難達到的值,比如100G,就可以間接禁用自動split(RegionServer不會對未到達100G的region做split)。
再配合
RegionSplitter這個工具,在需要split時,手動split。
手動split在靈活性和穩定性上比起自動split要高很多,相反,管理成本增加不多,比較推薦online實時系統使用。

內存方面,小region在設置memstore的大小值上比較靈活,大region則過大過小都不行,過大會導致flush時app的IO wait增高,過小則因store file過多影響讀性能。

hbase.regionserver.global.memstore.upperLimit/lowerLimit

默認值:0.4/0.35
upperlimit說明:hbase.hregion.memstore.flush.size 這個參數的作用是當單個Region內所有的memstore大小總和超過指定值時,flush該region的所有memstore。RegionServer的flush是通過將請求添加一個隊列,模擬生產消費模式來異步處理的。那這裏就有一個問題,當隊列來不及消費,產生大量積壓請求時,可能會導致內存陡增,最壞的情況是觸發OOM。
這個參數的作用是防止內存佔用過大,當ReigonServer內所有region的memstores所佔用內存總和達到heap的40%時,HBase會強制block所有的更新並flush這些region以釋放所有memstore佔用的內存。
lowerLimit說明: 同upperLimit,只不過lowerLimit在所有region的memstores所佔用內存達到Heap的35%時,不flush所有的memstore。它會找一個memstore內存佔用最大的region,做個別flush,此時寫更新還是會被block。lowerLimit算是一個在所有region強制flush導致性能降低前的補救措施。在日誌中,表現爲 “** Flush thread woke up with memory above low water.”
調優:這是一個Heap內存保護參數,默認值已經能適用大多數場景。
參數調整會影響讀寫,如果寫的壓力大導致經常超過這個閥值,則調小讀緩存hfile.block.cache.size增大該閥值,或者Heap餘量較多時,不修改讀緩存大小。
如果在高壓情況下,也沒超過這個閥值,那麼建議你適當調小這個閥值再做壓測,確保觸發次數不要太多,然後還有較多Heap餘量的時候,調大hfile.block.cache.size提高讀性能。
還有一種可能性是?hbase.hregion.memstore.flush.size保持不變,但RS維護了過多的region,要知道 region數量直接影響佔用內存的大小。

hfile.block.cache.size

默認值:0.2
說明:storefile的讀緩存佔用Heap的大小百分比,0.2表示20%。該值直接影響數據讀的性能。
調優:當然是越大越好,如果寫比讀少很多,開到0.4-0.5也沒問題。如果讀寫較均衡,0.3左右。如果寫比讀多,果斷默認吧。設置這個值的時候,你同時要參考?hbase.regionserver.global.memstore.upperLimit?,該值是memstore佔heap的最大百分比,兩個參數一個影響讀,一個影響寫。如果兩值加起來超過80-90%,會有OOM的風險,謹慎設置。

hbase.hstore.blockingStoreFiles

默認值:7
說明:在flush時,當一個region中的Store(Coulmn Family)內有超過7個storefile時,則block所有的寫請求進行compaction,以減少storefile數量。
調優:block寫請求會嚴重影響當前regionServer的響應時間,但過多的storefile也會影響讀性能。從實際應用來看,爲了獲取較平滑的響應時間,可將值設爲無限大。如果能容忍響應時間出現較大的波峯波谷,那麼默認或根據自身場景調整即可。

hbase.hregion.memstore.block.multiplier

默認值:2
說明:當一個region裏的memstore佔用內存大小超過hbase.hregion.memstore.flush.size兩倍的大小時,block該region的所有請求,進行flush,釋放內存。
雖然我們設置了region所佔用的memstores總內存大小,比如64M,但想象一下,在最後63.9M的時候,我Put了一個200M的數據,此時memstore的大小會瞬間暴漲到超過預期的hbase.hregion.memstore.flush.size的幾倍。這個參數的作用是當memstore的大小增至超過hbase.hregion.memstore.flush.size 2倍時,block所有請求,遏制風險進一步擴大。
調優: 這個參數的默認值還是比較靠譜的。如果你預估你的正常應用場景(不包括異常)不會出現突發寫或寫的量可控,那麼保持默認值即可。如果正常情況下,你的寫請求量就會經常暴長到正常的幾倍,那麼你應該調大這個倍數並調整其他參數值,比如hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以預留更多內存,防止HBase server OOM。

hbase.hregion.memstore.mslab.enabled

默認值:true
說明:減少因內存碎片導致的Full GC,提高整體性能。
調優:詳見 
http://kenwublog.com/avoid-full-gc-in-hbase-using-arena-allocation

其他

啓用LZO壓縮
LZO對比Hbase默認的GZip,前者性能較高,後者壓縮比較高,具體參見?Using LZO Compression 。對於想提高HBase讀寫性能的開發者,採用LZO是比較好的選擇。對於非常在乎存儲空間的開發者,則建議保持默認。

不要在一張表裏定義太多的Column Family

Hbase目前不能良好的處理超過包含2-3個CF的表。因爲某個CF在flush發生時,它鄰近的CF也會因關聯效應被觸發flush,最終導致系統產生更多IO。

批量導入

在批量導入數據到Hbase前,你可以通過預先創建regions,來平衡數據的負載。詳見?Table Creation: Pre-Creating Regions

避免CMS concurrent mode failure

HBase使用CMS GC。默認觸發GC的時機是當年老代內存達到90%的時候,這個百分比由 -XX:CMSInitiatingOccupancyFraction=N 這個參數來設置。concurrent mode failed發生在這樣一個場景:
當年老代內存達到90%的時候,CMS開始進行併發垃圾收集,於此同時,新生代還在迅速不斷地晉升對象到年老代。當年老代CMS還未完成併發標記時,年老代滿了,悲劇就發生了。CMS因爲沒內存可用不得不暫停mark,並觸發一次stop the world(掛起所有jvm線程),然後採用單線程拷貝方式清理所有垃圾對象。這個過程會非常漫長。爲了避免出現concurrent mode failed,建議讓GC在未到90%時,就觸發。

通過設置?-XX:CMSInitiatingOccupancyFraction=N

這個百分比, 可以簡單的這麼計算。如果你的?hfile.block.cache.size 和?hbase.regionserver.global.memstore.upperLimit 加起來有60%(默認),那麼你可以設置 70-80,一般高10%左右差不多。

 

hbase.balancer.period

hbase自身進行balance操作的間隔時間,默認爲300000,以依情況而定。也可關閉,通過對region的監控,手動調整region。


 

hbase.client.pause

client在寫時會進行多次的重試,重試的間隔採用的是指數避讓的方法,間隔時間爲1秒,即爲1000,

在默認10次重試的情況下,就會是這樣的間隔時間:[1,1,1,2,2,4,4,8,16,32],

從這可以看出當server出現異常時會導致client長時間的等待,因此可以將client的重試間隔時間調短爲20ms


 

hbase.hregion.max.filesize

如果region是手動split,建議大小在100G或者更大(設置一個不可達到的值),如果是自動split,建議在1G-2G之間

 

Hbase客戶端優化

AutoFlush

HTable的setAutoFlush設爲false,可以支持客戶端批量更新。即當Put填滿客戶端flush緩存時,才發送到服務端。
默認是true。

Scan Caching

scanner一次緩存多少數據來scan(從服務端一次抓多少數據回來scan)。
默認值是 1,一次只取一條。

Scan Attribute Selection

scan時建議指定需要的Column Family,減少通信量,否則scan操作默認會返回整個row的所有數據(所有Coulmn Family)。

Close ResultScanners

通過scan取完數據後,記得要關閉ResultScanner,否則RegionServer可能會出現問題(對應的Server資源無法釋放)。

Optimal Loading of Row Keys

當你scan一張表的時候,返回結果只需要row key(不需要CF, qualifier,values,timestaps)時,你可以在scan實例中添加一個filterList,並設置 MUST_PASS_ALL操作,filterList中add?FirstKeyOnlyFilterKeyOnlyFilter。這樣可以減少網絡通信量。

Turn off WAL on Puts

當Put某些非重要數據時,你可以設置writeToWAL(false),來進一步提高寫性能。writeToWAL(false)會在Put時放棄寫WAL log。風險是,當RegionServer宕機時,可能你剛纔Put的那些數據會丟失,且無法恢復。

啓用Bloom Filter

Bloom Filter通過空間換時間,提高讀操作性能。

最後,感謝嬴北望同學對”hbase.hregion.memstore.flush.size”和“hbase.hstore.blockingStoreFiles”錯誤觀點的修正。

本文轉自:http://kenwublog.com/hbase-performance-tuning

 

 

提升hbase性能的幾個地方(轉載)

1、使用bloomfilter和mapfile_index_interval

Bloomfilter(開啓/未開啓=1/0) mapfile_index_interval Exists(0-10000)/ms Get(10001 - 20000)/ms
0 128 22460 23715
0 0 11897 11416
0 64 13692 14034
1 128 3275 3686
1 64 2961 3010
1 0 3339 3498
       
測試環境爲:單機,規模爲10萬條數據。隨機在10000條數據中有99條存在的情況下。      
結論:開啓bloomfilter比沒開啓要快3、4倍。而適當的減少mapfile_index_interval可以提升性能      

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

注意:在1.9.3版本的hbase中,bloomfilter是不支持的,存在一個bug,可以通過如下的修改加以改正:
    (1)、在方法org.apache.hadoop.hbase.regionserver.HStore.createReaders()中,找到如下行
    BloomFilterMapFile.Reader reader = file.getReader(fs, false, false);
    將其改成
    BloomFilterMapFile.Reader reader = file.getReader(fs, this.family.isBloomfilter(), false);
    (2)、在方法org.apache.hadoop.hbase.HColumnDescriptor.toString()中,找到如下的代碼行
      if (key != null && key.toUpperCase().equals(BLOOMFILTER)) {
        // Don't emit bloomfilter.  Its not working.
        continue;
      }
    將其註釋掉

2、hbase對於內存有特別的嗜好,在硬件允許的情況下配足夠多的內存給它。
    通過修改hbase-env.sh中的
    export HBASE_HEAPSIZE=3000 #這裏默認爲1000m

3、修改java虛擬機屬性
    (1)、在環境允許的情況下換64位的虛擬機
    (2)、替換掉默認的垃圾回收器,因爲默認的垃圾回收器在多線程環境下會有更多的wait等待
    export HBASE_OPTS="-server -XX:NewSize=6m -XX:MaxNewSize=6m -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode"

4、增大RPC數量
    通過修改hbase-site.xml中的    
    hbase.regionserver.handler.count屬性,可以適當的放大。默認值爲10有點小

5、做程序開發是注意的地方
    (1)、需要判斷所求的數據行是否存在時,儘量不要用HTable.exists(final byte [] row) 而用HTable.exists(final byte [] row, final byte[] column)等帶列族的方法替代。
    (2)、不要使用HTable.get(final byte [] row, final byte [] column) == null來判斷所求的數據存在,而是用HTable.exists(final byte [] row, final byte[] column)替代
    (3)、HTable.close()方法少用.因爲我遇到過一些很令人費解的錯誤

6、記住HBase是基於列模式的存儲,如果一個列族能搞定就不要把它分開成兩個,關係數據庫的那套在這裏很不實用.分成多個列來存儲會浪費更多的空間,除非你認爲現在的硬盤和白菜一個價。

7、如果數據量沒有達到TB級別或者沒有上億條記錄,很難發揮HBase的優勢,建議換關係數據庫或別的存儲技術。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章