HBase效能優化完全版
近期在處理HBase的業務方面常常遇到各種瓶頸,一天大概一億條資料,在HBase效能調優方面進行相關配置和調優後取得了一定的成效,於是,特此在這裡總結了一下關於HBase全面的配置,主要參考我的另外兩篇文章:
在其基礎上總結出來的效能優化方法。
1.垃圾回收優化
Java本身提供了垃圾回收機制,依靠JRE對程式行為的各種假設進行垃圾回收,但是HBase支援海量資料持續入庫,非常佔用記憶體,因此繁重的負載會迫使記憶體分配策略無法安全地依賴於JRE的判斷:需要調整JRE的引數來調整垃圾回收策略。有關java記憶體回收機制的問題具體請參考:http://my.oschina.net/sunnywu/blog/332870
(1)HBASE_OPTS或者HBASE_REGIONSERVER_OPT變數來設定垃圾回收的選項,後面一般是用於配置RegionServer的,需要在每個子節點的HBASE_OPTS檔案中進行配置。
1)首先是設定新生代大小的引數,不能過小,過小則導致年輕代過快成為老生代,引起老生代產生記憶體隨便。同樣不能過大,過大導致所有的JAVA程序停止時間長。-XX:MaxNewSize=256m-XX:NewSize=256m 這兩個可以合併成為-Xmn256m這一個配置來完成。
2)其次是設定垃圾回收策略:-XX:+UseParNewGC -XX:+UseConcMarkSweepGC也叫收集器設定。
3)設定CMS的值,佔比多少時,開始併發標記和清掃檢查。-XX:CMSInitiatingOccupancyFraction=70
4)列印垃圾回收資訊:-verbose:gc -XX: +PrintGCDetails -XX:+PrintGCTimeStamps
-Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log
最終可以得到:HBASE_REGIONSERVER_OPT="-Xmx8g -Xms8g –Xmn256m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC \
-XX:CMSInitiatingOccupancyFraction=70 -verbose:gc \
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps \
-Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log
(2)hbase.hregion.memstore.mslab.enabled預設值:true,這個是在hbase-site.xml中進行配置的值。
說明:減少因記憶體碎片導致的Full GC,提高整體效能。
2.啟用壓縮,詳情自行搜尋,暫時未曾嘗試,後面持續更新。
3.優化Region拆分合並以及與拆分Region
(1)hbase.hregion.max.filesize預設為256M(在hbase-site.xml中進行配置),當region達到這個閾值時,會自動拆分。可以把這個值設的無限大,則可以關閉HBase自動管理拆分,手動執行命令來進行region拆分,這樣可以在不同的region上交錯執行,分散I/O負載。
(2)預拆分region
使用者可以在建表的時候就制定好預設定的region,這樣就可以避免後期region自動拆分造成I/O負載。
4.客戶端入庫調優
(1)使用者在編寫程式入庫時,HBase的自動刷寫是預設開啟的,即使用者每一次put都會提交到HBase server進行一次刷寫,如果需要高速插入資料,則會造成I/O負載過重。在這裡可以關閉自動刷寫功能,setAutoFlush(false)。如此,put例項會先寫到一個快取中,這個快取的大小通過hbase.client.write.buffer這個值來設定快取區,當快取區被填滿之後才會被送出。如果想要顯示刷寫資料,可以呼叫flushCommits()方法。
此處引申:採取這個方法要估算伺服器端記憶體佔用則可以:hbase.client.write.buffer*hbase.regionserver.handler.count得出記憶體情況。
(2)第二個方法,是關閉每次put上的WAL(writeToWAL(flase))這樣可以刷寫資料前,不需要預寫日誌,但是如果資料重要的話建議不要關閉。
(3)hbase.client.scanner.caching:預設為1
這是設計客戶端讀取資料的配置調優,在hbase-site.xml中進行配置,代表scanner一次快取多少資料(從伺服器一次抓取多少資料來scan)預設的太小,但是對於大檔案,值不應太大。
(4)hbase.regionserver.lease.period預設值:60000
說明:客戶端租用HRegion server 期限,即超時閥值。
調優:這個配合hbase.client.scanner.caching使用,如果記憶體夠大,但是取出較多資料後計算過程較長,可能超過這個閾值,適當可設定較長的響應時間以防被認為宕機。
(5)還有諸多實踐,如設定過濾器,掃描快取等,指定行掃描等多種客戶端調優方案,需要在實踐中慢慢挖掘。
5.HBase配置檔案
上面涉及到的調優內容或多或少在HBase配置檔案中都有所涉及,因此,下面的配置不涵蓋上面已有的配置。
(1) zookeeper.session.timeout(預設3分鐘)
ZK的超期引數,預設配置為3分鐘,在生產環境上建議減小這個值在1分鐘或更小。
設定原則:這個值越小,當RS故障時Hmaster獲知越快,Hlog分裂和region 部署越快,叢集恢復時間越短。 但是,設定這個值得原則是留足夠的時間進行GC回收,否則會導致頻繁的RS宕機。一般就做預設即可
(2)hbase.regionserver.handler.count(預設10)
對於大負載的put(達到了M範圍)或是大範圍的Scan操作,handler數目不易過大,易造成OOM。 對於小負載的put或是get,delete等操作,handler數要適當調大。根據上面的原則,要看我們的業務的情況來設定。(具體情況具體分析)。
(3)HBASE_HEAPSIZE(hbase-env.sh中配置)
我的前兩篇文章Memstoresize40%(預設) blockcache 20%(預設)就是依據這個而成的,總體HBase記憶體配置。設到機器記憶體的1/2即可。
(4)選擇使用壓縮演算法,目前HBase預設支援的壓縮演算法包括GZ,LZO以及snappy(hbase-site.xml中配置)
(5)hbase.hregion.max.filesize預設256M
上面說過了,hbase自動拆分region的閾值,可以設大或者無限大,無限大需要手動拆分region,懶的人別這樣。
(6)hbase.hregion.memstore.flush.size
單個region內所有的memstore大小總和超過指定值時,flush該region的所有memstore。
(7)hbase.hstore.blockingStoreFiles 預設值:7
說明:在flush時,當一個region中的Store(CoulmnFamily)內有超過7個storefile時,則block所有的寫請求進行compaction,以減少storefile數量。
調優:block寫請求會嚴重影響當前regionServer的響應時間,但過多的storefile也會影響讀效能。從實際應用來看,為了獲取較平滑的響應時間,可將值設為無限大。如果能容忍響應時間出現較大的波峰波谷,那麼預設或根據自身場景調整即可。
(8)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。
(9)hbase.regionserver.global.memstore.upperLimit:預設40%
當ReigonServer內所有region的memstores所佔用記憶體總和達到heap的40%時,HBase會強制block所有的更新並flush這些region以釋放所有memstore佔用的記憶體。
hbase.regionserver.global.memstore.lowerLimit:預設35%
同upperLimit,只不過lowerLimit在所有region的memstores所佔用記憶體達到Heap的35%時,不flush所有的memstore。它會找一個memstore記憶體佔用最大的region,做個別flush,此時寫更新還是會被block。lowerLimit算是一個在所有region強制flush導致效能降低前的補救措施。在日誌中,表現為 “** Flushthread woke up with memory above low water.”。
調優:這是一個Heap記憶體保護引數,預設值已經能適用大多數場景。
(10)hfile.block.cache.size:預設20%
這是涉及hbase讀取檔案的主要配置,BlockCache主要提供給讀使用。讀請求先到memstore中查資料,查不到就到blockcache中查,再查不到就會到磁碟上讀,並把讀的結果放入blockcache。由於blockcache是一個LRU,因此blockcache達到上限(heapsize * hfile.block.cache.size)後,會啟動淘汰機制,淘汰掉最老的一批資料。對於注重讀響應時間的系統,應該將blockcache設大些,比如設定blockcache=0.4,memstore=0.39,這會加大快取命中率。
(11)hbase.regionserver.hlog.blocksize和hbase.regionserver.maxlogs
之所以把這兩個值放在一起,是因為WAL的最大值由hbase.regionserver.maxlogs*hbase.regionserver.hlog.blocksize (2GB by default)決定。一旦達到這個值,Memstore flush就會被觸發。所以,當你增加Memstore的大小以及調整其他的Memstore的設定項時,你也需要去調整HLog的配置項。否則,WAL的大小限制可能會首先被觸發,因而,你將利用不到其他專門為Memstore而設計的優化。拋開這些不說,通過WAL限制來觸發Memstore的flush並非最佳方式,這樣做可能會會一次flush很多Region,儘管“寫資料”是很好的分佈於整個叢集,進而很有可能會引發flush“大風暴”。
提示:最好將hbase.regionserver.hlog.blocksize* hbase.regionserver.maxlogs 設定為稍微大於hbase.regionserver.global.memstore.lowerLimit* HBASE_HEAPSIZE。
6.HDFS優化部分
HBase是基於hdfs檔案系統的一個數據庫,其資料最終是寫到hdfs中的,因此涉及hdfs調優的部分也是必不可少的。
(1)dfs.replication.interval:預設3秒
可以調高,避免hdfs頻繁備份,從而提高吞吐率。
(2)dfs.datanode.handler.count:預設為10
可以調高這個處理執行緒數,使得寫資料更快
(3)dfs.namenode.handler.count:預設為8
(4)dfs.datanode.socket.write.timeout:預設480秒,併發寫資料量大的時候可以調高一些,否則會出現我另外一篇部落格介紹的的錯誤。
(5)dfs.socket.timeout:最好也要調高,預設的很小。
同上,可以調高,提高整體速度與效能。
以上就是hbase整體效能調優攻略,仍然會有遺漏的地方或補充,在實際中會慢慢完善,有不足的也請各位同仁指出!