HBase性能調優(1.2官方文檔)

HBase性能調優

一. 操作系統:

1.內存:

內存儘可能的大,不要餓着HBase。

2.64-bit

使用64位的操作系統。

3.Swapping

當心交換。swappiness設置爲0。

 

Linux 移動那些一段時間沒有被訪問的內存頁到 swap 空間,即使它由足夠可用的內存。這叫做 swap out。換一句話說,從 swap 空間讀 swapped out 的數據到內存中叫做 swap in。Swapping 在大多數情形是有必要的,但是因爲 Java Virtual Machine(JVM) 在 swapping 下不是表現的很好,如果 swapped 了,HBase 運行可能會遇到問題。ZooKeeper 的 session 過期或許是 被 swap 引入的典型問題。

 

vm.swappiness 設置成 0,這將使得內核避免把進程儘可能的從物理內存中交換出去。這對 HBase 是非常有用的,因爲 HBase 的進程消費大量的內存,一個高的 vm.swappiness 值將使得 HBase 交換很多並遭遇非常慢的垃圾回收。隨着 ZooKeeper session 超時,這可能會導致 RegionServer 進程被殺死。

 

如何修改swappiness:

查看

cat /proc/sys/vm/swappiness

修改

sysctlvm.swappiness=10

永久修改

echo"vm.swappiness = 10" >> /etc/sysctl.conf
 

4.CPU

確保您已經設置了您的Hadoop使用本地的、硬件的校驗和。(core-site.xml io.native.lib.available=true

 

二.網絡:

三.java

1.GC垃圾回收器

在HBase中有兩種stop-the-world GC的情況: CMS(併發GC)失效模式和老年代碎片問題。

第一個問題:

       啓動CMS前,將-XX:CMSInitiatingOccupancyFraction參數設置爲低於默認值(92),以60或70%啓動(降低閾值越低,完成的GCing越多,使用的CPU越多)

第二個問題:

本地memstore分配緩衝區MSLAB --代價是更加浪費堆空間

緩解由於memstore的擾動(不斷創建和釋放內存空間)造成region server 內存碎片問題。

原理:只允許從堆中分配相同的對象。一旦這些對象分配並且最終被回收,他們將在堆中留下固定大小的孔洞。之後調用相同大小的新對象將會重新使用這些孔洞:這樣就不會產生提升錯誤,因此就不需要應用程序停止壓縮回收了。默認在0.92版中被啓用,0.90版本未啓用,可以修改參數:hbase.hregion.memstore.mslab.enabled來覆蓋

       要注意的是,當啓用這個屬性時,每個MemStore實例將至少佔用一個內存實例。如果你在大量列族中都有成千上萬個region,可能會浪費很大的堆空間,嚴重時導致OOME。在這種情況下要禁用MSLAB或者降低它的內存使用量,或者減少region server 中的region數量。

       如果寫壓力過大,減少年輕代GC的配置。

       在hbase-env.sh 中配置GC-xx:PretenureSizeThreshold小於hbase.hregion.memstore.mslab.chunksize(默認2M的大小。

 

四.HBase 配置參數

1. hbase.regionserver.handler.count

hbase.regionserver.handler.count 該屬性定義了響應外部用戶訪問數據表請求的線程數。默認值10,較大的寫入和使用大緩存的掃描,設得小;而當單次請求開銷較小時(如get,較小的put,increment和delete等操作)可以將工作線程數設得高一些。

 

2. 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的風險,謹慎設置。

3. Blockcache預取選項

HBase shell:

 

hbase> create 'MyTable', { NAME => 'myCF', PREFETCH_BLOCKS_ON_OPEN => 'true' }
 

API:

 

HTableDescriptor tableDesc = new HTableDescriptor("myTable");
HColumnDescriptor cfDesc = new HColumnDescriptor("myCF");
cfDesc.setPrefetchBlocksOnOpen(true);
tableDesc.addFamily(cfDesc);

 

4. hbase.regionserver.global.memstore.size(默認HEAP_SIZE*0.4)

5. hbase.regionserver.global.memstore.size.lower.limit

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 lowwater.”

 

調優:這是一個Heap內存保護參數,默認值已經能適用大多數場景。
參數調整會影響讀寫,如果寫的壓力大導致經常超過這個閥值,則調小讀緩存hfile.block.cache.size增大該閥值,或者Heap餘量較多時,不修改讀緩存大小。
如果在高壓情況下,也沒超過這個閥值,那麼建議你適當調小這個閥值再做壓測,確保觸發次數不要太多,然後還有較多Heap餘量的時候,調大hfile.block.cache.size提高讀性能。
還有一種可能性是?hbase.hregion.memstore.flush.size保持不變,但RS維護了過多的region,要知道 region數量直接影響佔用內存的大小。hfile.block.cache.size

6.hbase.hstore.blockingStoreFiles

默認值:7
說明:在flush時,當一個region中的Store(Coulmn Family)內有超過7個storefile時,則block所有的寫請求進行compaction,以減少storefile數量。

 

調優:block寫請求會嚴重影響當前regionServer的響應時間,但過多的storefile也會影響讀性能。從實際應用來看,爲了獲取較平滑的響應時間,可將值設爲無限大。如果能容忍響應時間出現較大的波峯波谷,那麼默認或根據自身場景調整即可。

7. 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

 

 

8. hbase.regionserver.checksum.verify

 默認false,設置true,hbase使用自己的數據校驗,而不是hdfs的校驗;讓HBase把校驗和寫到數據庫中,並保存每次讀取時都要進行校驗和查找。

9.hbase.hregion.max.filesize

   默認10G,一個region下,任一列簇的hfiles的大小,超過這個值,該region將split成2個region。

  note:如果你的數據量增長的比較快,那麼還是建議把這個大小調高,可以調成100G,因爲越少的region你的集羣越流暢,100G的閾值基本可以避免你的region增長過快,甚至你的region數目會長期不變。當然大region在compaction時也會更加緩慢。幾十G的region啓動和compaction都非常的慢,如果storefile較多,一個compaction可能會持續幾天。

 

10. hbase.regionserver.maxlogs

默認爲32。它只要是控制WAL文件flush的頻率

 

如果寫操作比較多,那麼可以設置高一點。調低可以讓rs更快的把數據持久化,那麼就可以直接棄掉WAL了。其實寫操作比較多可以直接把WAL關閉,這樣更省事了。

 

11. hbase.hstore.compactionThreshold/hbase.hregion.majorcompaction

hbase.hstore.compactionThreshold執行compaction的store數量,默認值是3,如果需要提高查詢性能,當然是storefile的數量越小,性能越好,但是執行compaction本身有性能資源的開消,如果regionserver頻繁在 compacion對性能影響也很大。hbase.hregion.majorcompaction表示majorcompaction的週期,默認是1 天,majorcompaction與普通的compaction的區別是majorcompaction會清除過期的歷史版本數據,同時合併 storefile,而普通的compaction只做合併,通常都是majorcompaction

 

調爲0,然後手工定期的去執行一下 majorcompaction,適當調小點compacionThreshold。

 

 

12. hbase.regionserver.codecs

啓用數據壓縮,推薦Snappy或者LZO壓縮

13. hbase.master.wait.on.regionservers.mintostart

如果您有一個具有很多區域的羣集,則在主程序啓動後,所有其他RegionServers都會落後的情況下,Regionserver可能會進行短暫檢查。這個第一個要簽到的服務器將被分配給所有不是最優的區域,默認值1

 

增大數值

14. fail.fast.expired.active.master

如果master過期,那麼不需要從zk恢復,直接終止,默認是false;

改爲true

15.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的場景。

16. dfs.datanode.failed.volumes.tolerated

hdfs-site.xml       決定停止數據節點提供服務充許卷的出錯次數。默認值0,意思是任何卷出錯都要停止數據節點

 

改成2合適

 

 

五.客戶端API

當通過客戶端使用接口讀寫數據時:

1.禁止自動刷寫

2.使用掃描緩存

如果HBase被用作一個MAOReduce作業的輸入源,請最好將作爲MapReduce作業輸入掃描器實例的緩存用setCaching()方法設置爲比默認值1大得多的值。使用默認的值意味着map任務會在處理每條記錄時都請求region服務器。例如,將這個值設置爲500,則一次可以傳送500行數據到客戶端進行處理。這裏用戶需要權衡傳輸數據的開銷和內存的開銷,因爲緩存更大之後,無論是客戶端還是服務器端都將消耗更多內存緩存數據,所以大的緩存不一定最好。

3.限定掃描範圍

當scan被用來處理大量行時(特別是被用作MapReduce輸入源時),注意哪些屬性被選中了。如果Scan.addFamily()被調用了,那麼特定列族中的所有列都將會被返回到客戶端。如果只處理少數列,則應當只有這些列被添加到Scan的輸入中,因爲選擇了過多的列將導致在大數據集上極大的效率損失,這可不是一件小事。

4.關閉ResultScanner

在try/catch中的finally塊中關閉ResultScanner,避免一些問題。

5.塊緩存用法

Scan實例能夠通過setCacheBlocks()方法來設置使用region服務器中的塊緩存。如果MapReduce作業中使用掃描,這個方法應當被設置成false。對於那些頻繁訪問的行,建議使用塊緩存。

6.優化獲取行鍵的方式

當執行一個表的掃描以獲取需要的行鍵時(沒有列族/列名/列值和時間戳),在Scan中用setFilter()方法添加一個帶MUST_PASS_ALL操作符的FILterList。FilterList中包含FirstKeyFilter和KeyOnlyFilter兩個過濾器。使用以上組合的過濾器將會把發現的第一個KeyValue行鍵(也就是第一列的行鍵)返回給客戶端,這將會最大程度地減少網絡傳輸。

7.關閉Put上的WAL(危險)

 

六.HBase寫入

1.如果可以的話,用bulk load。

2.預創建分區

3.延遲日誌刷新

       WAL(預寫式日誌)默認行爲是立即寫入,如果開啓延遲刷新,日誌會先寫入內存中直到刷新週期,優點是聚合和異步寫入,但有一個風險,如果服務器宕機,未刷新的數據會宕機,但是總比不用WAL要安全。

       延遲刷新可以在HTableDescriptor中設置,也可以設置屬性hbase.regionserver.optionallogflushinterval(默認值1000ms)。

4.禁止自動刷寫

 當有大量的寫入操作時,使用setAutoFlush(false)方法,確認HTable自動刷寫的特性已經被關閉。否則Put實例將會被逐個傳送到region服務器。通過HTable.add(Put)和HTable.add(Put)添加的put實例都會添加到一個相同的寫入緩存中,如果用戶禁用了自動刷寫,這些操作直到寫緩衝區被填滿時纔會被送出。如果要顯式地刷寫數據,用戶可以調用flushCommits()方法。調用HTable實例的close方法也會隱式地調用flushCommits()。

5.關閉Put上的WAL

一個經常討論的提高寫吞吐量的方式是使用Put的writeToWAL(false)來關閉WAL。這樣服務器端就不會把這個Put寫入到WAL中,而只是把它寫到memstore裏,不過一旦region服務器出現故障就會丟失數據。如果用戶使用了writeToWAL(false),請小心。用戶可能會發現把數據在集羣間分佈均勻後,關閉日誌所帶來的性能提升並不明顯。

       總而言之,最好是在寫入數據時使用WAL,並且如果特別關心吞吐量的話,就用批量導入(bulk load)技術。

6.按RegionServer進行puts分組。

除了使用writeBuffer之外,按regionserver分組可以減少每個寫緩衝區刷新時的客戶端RPC調用的數量。可以調用HTableUtil實現,如果還在用0.90版本,可以自己實現。

7.跳過reducer

當將來自MR job的大量的數據寫入一個HBase表時,特別是從mapper釋放出來的,儘可能跳過reducer步驟(因爲如果有reducer,數據先會寫入磁盤,然後sortshuffle。。)。如果把HBase作爲sourcesink的話,數據會從reducer寫出(比如計算值並寫出結果),這是另一種情況。

 

8.避免熱點region

 

 

七.HBase讀取

1. 使用掃描緩存

如果HBase被用作一個MAOReduce作業的輸入源,請最好將作爲MapReduce作業輸入掃描器實例的緩存用setCaching()方法設置爲比默認值1大得多的值。使用默認的值意味着map任務會在處理每條記錄時都請求region服務器。例如,將這個值設置爲500,則一次可以傳送500行數據到客戶端進行處理。這裏用戶需要權衡傳輸數據的開銷和內存的開銷,因爲緩存更大之後,無論是客戶端還是服務器端都將消耗更多內存緩存數據,所以大的緩存不一定最好。

2. 掃描屬性選擇

無論何時使用掃描來處理大量的行(特別是當作爲MapReduce源使用時),請注意選擇了哪些屬性。如果調用scan.addFamily,在指定的ColumnFamily中所有的屬性將被返回給客戶端。如果只處理少量可用屬性,那麼只需要在輸入掃描中指定這些屬性,因爲屬性的過度選擇對於大型數據集來說是一個不小的性能損失。

3. 避免掃描搜索

當使用scan.addColumn顯式選擇列時。HBase將在選定的列之間安排查找操作。當行數很少時,每個列只有幾個版本,這可能是低效的。如果不至少查找5-10個列/版本或512-1024個字節,查找操作通常比較慢。

爲了能適時地查看一些列/版本,以查看下一個列/版本是否可以在一個查找操作之前找到,可以在掃描對象上設置一個新的屬性Scan.HINT_LOOKAHEAD。下面的代碼指導RegionServer尋找目標之前嘗試下兩個迭代:

 

Scan scan = new Scan();

scan.addColumn(...);

scan.setAttribute(Scan.HINT_LOOKAHEAD,Bytes.toBytes(2));

table.getScanner(scan);

 

4. MapReduce - Input Splits

對於使用HBase表作爲源的MapReduce作業,如果有一種情況,“慢”的map任務似乎有相同的輸入分割,看這裏:

 Case Study #1 (Performance Issue On ASingle Node).

5.關閉ResultScanner

在try/catch中的finally塊中關閉ResultScanner,避免一些問題。

6.塊緩存用法

Scan實例能夠通過setCacheBlocks()方法來設置使用region服務器中的塊緩存。如果MapReduce作業中使用掃描,這個方法應當被設置成false。對於那些頻繁訪問的行,建議使用塊緩存。

7.優化獲取行鍵的方式

當執行一個表的掃描以獲取需要的行鍵時(沒有列族/列名/列值和時間戳),在Scan中用setFilter()方法添加一個帶MUST_PASS_ALL操作符的FILterList。FilterList中包含FirstKeyFilter和KeyOnlyFilter兩個過濾器。使用以上組合的過濾器將會把發現的第一個KeyValue行鍵(也就是第一列的行鍵)返回給客戶端,這將會最大程度地減少網絡傳輸。

 

8. 併發性:監測數據傳播

在執行大量併發讀操作時,監視目標表的數據傳播。如果目標表的region太少,那麼讀操作可能會從很少的節點進行。

9. Bloom 過濾器

 

10. 對衝讀取

對衝讀取是HDFS-5776中引入的HDFS的一個特性。通常,爲每個讀請求生成一個線程。但是,如果啓用了對衝操作,客戶端會等待一些可配置的時間,如果讀取不返回,則客戶端會生成第二個read請求,針對相同數據的不同塊複製。無論使用哪個讀取返回,都將丟棄另一個讀取請求。當一個罕見的慢讀操作是由一個錯誤的磁盤或脆弱的網絡連接引起的短暫的錯誤時,對其進行對衝操作可能會有幫助。

 

因爲HBaseRegionServer是一個HDFS客戶端,所以可以在HBase中啓用對衝操作,通過將以下屬性添加到RegionServer節點。

 

<property>

  <name>dfs.client.hedged.read.threadpool.size</name>

  <value>20</value> <!-- 20 threads 設置爲0不啓用-->

</property>

<property>

  <name>dfs.client.hedged.read.threshold.millis</name>

  <value>10</value> <!-- 10 milliseconds 啓動第二個個線程等待的毫秒數-->

</property>

 

 

八.HBase刪除

1.使用HBase表作爲隊列

HBase表有時被用作隊列。在這種情況下,必須採取特別的措施,定期對以這種方式使用的表執行major compactions。正如在數據模型中記錄的那樣,標記行被刪除會創建額外的store文件,然後需要在讀取過程中進行處理。殘留只有在major compactions情況下才會被清理乾淨。

2.刪除 RPC行爲

注意,table.delete(Delete)不使用writeBuffer。它將在每次調用時執行一個RegionServer RPC。對於大量的刪除操作,請考慮table.delete(List)。

九.HDFS

配置短讀:

<property>

  <name>dfs.client.read.shortcircuit</name>

  <value>true</value>

  <description>

    This configuration parameter turns onshort-circuit local reads.

  </description>

</property>

 

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