您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關HBase如何管理以及性能調優,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
因為 HBase 運行在 JVM,JVM 的 Garbage Collection(GC) 設置對于 HBase 流暢的運行,更高的性能是非常重要的,除了配置 HBase 堆設置的指導方針之外。有 HBase 進程輸出到它們的 GC 日志中是同樣重要的,并且它們基于 GC 日志的輸出調整 JVM 設置。
我將描述最重要的 HBase JVM 堆設置,也描述怎樣是它生效以及理解 GC 日志,在這方面。我將覆蓋一些指導方針來調整 HBase 的 Java GC 設置。
登陸你的 HBase region 服務器。
以下被建議用于 Java GC 和 HBase 堆設置:
通過編輯 hbase-env.sh 文件給 HBase 足夠大的堆大小。比如,以下片段給 HBase 配置一個 8000-MB 的堆:
$ vi $HBASE_HOME/conf/hbase-env.shexport HBASE_HEAPSIZE=8000
通過以下命令使得 GC 日志生效:
export HBASE_OPTS="$HBASE_OPTS -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/usr/local/hbase/logs/gc-hbase.log"
把以下代碼加入來比默認更早的開始 Concurrent-Mark-Sweep GC(CMS):
$ vi $HBASE_HOME/conf/hbase-env.shexport HBASE_OPTS="$HBASE_OPTS -XX:CMSInitiatingOccupancyFraction=60"
在集群中同步變更并重啟 HBase。
檢查輸出到指定日志文件中(/usr/local/hbase/logs/gc-hbase.log)的 GC 日志。GC 日志看起來像以下屏幕截圖:
在步驟 1 中,我們配置 HBase 堆內存大小。默認,HBase 使用 1GB 的堆,這對于現代的機器來說太低了。對于 HBase 來說,比 4GB 更大是好的。我們建議 8GB 或更大,但是低于 16 GB。
在步驟 2 中,我們是 JVM 日志生效,使用這個設置,你可以獲取 region 服務器的 JVM 日志,和我們在步驟 5 中展示的類似。關于 JVM 內存分配和垃圾回收的基礎知識是被要求的,為了明白日志輸出。以下是 JVM 分代垃圾收集系統的圖表:
這里有 3 個堆分代:Perm(或是 Permanent)代【永久代】,Old Generation 代【老年代】,和 Young 代【年輕代】。年輕代由三個獨立的空間組成,Eden 空間和兩個 survivor 空間,S0 和 S1。
通常,對象被分配在年輕代的 Eden 空間,如果一個分配失敗(Eden 滿了),所有 java 線程停止,并且一個年輕代 GC(Minor GC)被調用。所有在年輕代存活的對象(Eden 和 S0 空間)被拷貝到 S1 空間。如果 S1 空間滿了,對象被拷貝(提升)到老年代。當一個提升失敗,老年代被收集(Major/Full GC)。永久代和老年代通常一起被收集。永久代被用于在存放類和對象中定義的方法。
回到我們示例的步驟 5,上述選項產出的 minor GC 輸出為以下形式:
<timestamp>: [GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs] [Times: <user time> <system time>, <real time>]
在這個輸出中:
timestamp 是 GC 發生的時間,相對于應用的啟動時間。
collector 是 collector 用于 minor collection 的內部名字
starting occupancy1 是年輕代在垃圾回收前的占用
ending occupancy1 是年輕代在垃圾回收后的占用
pause time1 是 minor collection 中斷的時間
starting occupancy3 是在垃圾回收前整個堆的占用
ending occupancy3 是在垃圾回收后整個堆的占用
pause time3 是整個垃圾回收的中斷時間,這包括 major collection。
[Time:] 解釋了花費在垃圾收集的時間,用戶時間,系統時間,實際時間。
在步驟 5 中我們輸出的第一行表明了是一個 minor GC,中斷了 JVM 0.0764200 秒,它已經把年輕代的空間從 14.8MB 降低到 1.6MB。
接著,我們看看 CMS GC 日志,HBase 使用 CMS GC 作為它默認的老年代垃圾回收器。
CMS GC 執行以下步驟:
初始化標記
并發標記
重復標記
并發休眠
CMS 僅僅在它初始化標記和重復標記的階段中斷應用進程。在并發標記和睡眠階段,CMS 線程隨著應用線程一起運行。
在該示例的第二行表明了 CMS 初始化標記花費了 0.0100050 秒,并發標記花費了 6.496 秒。注意,并發標記,Java 不會被中斷。
在 GC 日志的早期屏幕截圖中,在行開始于 1441.435: [GC[YG occupancy:…] 的地方有一個中斷。這里的中斷是 0.0413960 秒,用于重復標記堆。之后,你可以看到睡眠開始了。CMS 睡眠花費了 3.446 秒,但是堆大小在這里沒有變化太多(它繼續占據大約 150MB)。
這里的調整點是使得所有的中斷時間更低。為了保持中斷時間更低,你需要使用 -XX:NewSize 和 -XX:MaxNewSize JVM 參數調整年輕代空間大小,為了將它們設置為相對較小的值(比如,調高幾百 MB)。如果服務器有更多的 CPU 資源,我們建議通過設置 -XX:+UseParNewGC 選項使用 Parallel New Collector。你或許也想為你的年輕代調整 parallel GC 線程數量,通過 -XX:ParallelGCThreads JVM 參數。
我們建議加入上述設置到 HBASE_REGIONSERVER_OPTS 變量中,代替 hbase-env.sh 文件中的 HBASE_OPTS 變量。HBASE_REGIONSERVER_OPTS 僅僅影響 region 服務器的進程,這非常好,因為 HBase master 既不處理重型任務也不參與數據處理。
對于老年代來說, concurrent collection (CMS) 通常不能被加速,但是它可以更早的開始。當分配在老年代的空間比率超過了一個閥值,CMS 開始運行。這個閥值是被收集器自動計算的。對于有些情況,特別是在加載期間,如果 CMS 開始的太晚,HBase 或許會直接進行 full garbage collection。為了避免這個,我們建議設置 -XX:CMSInitiatingOccupancyFraction JVM 參數來精確指定在多少百分比 CMS 應該被開始,正如我們在步驟 3 中做的那樣。在 百分之 60 或 70 開始是一個好的實踐。當老年代使用 CMS,默認的年輕代 GC 將被設置成 Parallel New Collector。
如果你之前使用的是 HBase 0.92 版本,考慮使用 MemStore-Local 分配 Buffer 來預防老年代堆碎片,在頻繁寫的負載下:
$ vi $HBASE_HOME/conf/hbase-site.xml <property> <name>hbase.hregion.memstore.mslab.enabled</name> <value>true</value> </property>
這個特性在 HBase 0.92 中是默認開啟的。
HBase 另外一個最重要的特性就是使用壓縮。它是非常重要的,因為:
壓縮降低從 HDFS 讀寫的字節數
節約磁盤空間
當從一個遠程服務器獲取數據的時候,提升了網絡帶寬的效率
HBase 支持 GZip 和 LZO 格式,我的建議是使用 LZO 壓縮算法,因為它解壓數據快并且 CPU 使用率低。更好的壓縮比是系統的首選,你應該考慮 GZip。
不幸的是,HBase 不能使用 LZO,因為 license 問題。HBase 是 Apache-licensed,然而 LZO 是 GPL-licensed。因此,我們需要自己安裝 LZO。我們將使用 hadoop-lzo 庫,給 Hadoop 帶來了變形的 LZO 算法。
在這方面,我們將描述怎樣安裝 LZO 和怎樣配置 HBase 使用 LZO 壓縮。
確保在 hadoop-lzo 被構建的機器上 Java 安裝了。Apache Ant 被要求用來從源碼構建 hadoop-lzo。通過運行一下命令來安裝 Ant:
$ sudo apt-get -y install ant
集群中的所有節點需要有原生的 LZO 庫被安裝。你可以通過使用以下命令安裝:
$ sudo apt-get -y install liblzo2-dev
我們將使用 hadoop-lzo 庫來給 HBase 添加 LZO 壓縮支持:
從 https://github.com/toddlipcon/hadoop-lzo 獲取最新的 hadoop-lzo 源碼
從源碼構建原生的 hadoop-lzo 庫。依賴于你的 OS,你應該選擇構建 32-bit 或 64-bit 的二進制包。比如,為了構建 32-bit 二進制包,運行以下命令:
$ export JAVA_HOME="/usr/local/jdk1.6"$ export CFLAGS="-m32"$ export CXXFLAGS="-m32"$ cd hadoop-lzo$ ant compile-native$ ant jar
這些命令將創建 hadoop-lzo/build/native 目錄和 hadoop-lzo/build/hadoop-lzo-x.y.z.jar 文件。為了構建 64-bit 二進制包,你需要改變 CFLAGS 和 CXXFLAGS 成 m64。
拷貝構建的包到你master 節點的 $HBASE_HOME/lib 和 $HBASE_HOME/lib/native 目錄:
hadoop@master1$ cp hadoop-lzo/build/hadoop-lzo-x.y.z.jar $HBASE_HOME/lib hadoop@master1$ mkdir $HBASE_HOME/lib/native/Linux-i386-32hadoop@master1$ cp hadoop-lzo/build/native/Linux-i386-32/lib/* $HBASE_HOME/lib/native/Linux-i386-32/
對于一個 64-bit OS,把 Linux-i386-32 改變成(在前面步驟中) Linux-amd64-64。
添加 hbase.regionserver.codecs 的配置到你的 hbase-site.xml 文件:
hadoop@master1$ vi $HBASE_HOME/conf/hbase-site.xml<property><name>hbase.regionserver.codecs</name><value>lzo,gz</value></property>
在集群中同步 $HBASE_HOME/conf 和 $HBASE_HOME/lib 目錄。
HBase ships 使用一個工具來測試壓縮是否被正確設置了。使用這個工具來在集群中的每個節點上測試 LZO 設置。如果一切都正確無誤的配置了,你將得到成功的輸出:
hadoop@client1$ $HBASE_HOME/bin/hbase org.apache.hadoop.hbase.util.CompressionTest /tmp/lzotest lzo12/03/11 11:01:08 INFO hfile.CacheConfig: Allocating LruBlockCache with maximum size 249.6m12/03/11 11:01:08 INFO lzo.GPLNativeCodeLoader: Loaded native gpl library12/03/11 11:01:08 INFO lzo.LzoCodec: Successfully loaded & initialized native-lzo library [hadoop-lzo rev Unknown build revision]12/03/11 11:01:08 INFO compress.CodecPool: Got brand-new compressor12/03/11 11:01:18 INFO compress.CodecPool: Got brand-new decompressor SUCCESS
通過使用 LZO 壓縮創建一個表來測試配置,并在 HBase Shell 中驗證它:
$ hbase> create 't1', {NAME => 'cf1', COMPRESSION => 'LZO'} $ hbase> describe 't1'DESCRIPTION ENABLED {NAME => 't1', FAMILIES => [{NAME => 'cf1', BLOOMFILTER => 'NONE', true REPLICATION_SCOPE => '0', VERSIONS => '3', COMPRESSION => 'LZO', MIN_VERSIONS => '0', TTL => '2147483647', BLOCKSIZE => '65536', IN _MEMORY => 'false', BLOCKCACHE => 'true'}]} 1 row(s) in 0.0790 seconds
hbase.hregion.majorcompaction 屬性指定了在 region 上所有存儲文件之間的 major compactions 時間。默認是時間是 86400000,即一天。我們在步驟 1 中把它設置為 0,是禁止自動的 major compaction。這將預防 major compaction 在繁忙加載時間運行,比如當 MapReduce 任務正運行在 HBase 集群上。
換句話說, major compaction 被要求來幫助提升性能。在步驟 4 中,我們已經展示了通過 HBase Shell 怎樣在一個特別的 region 上手動觸發 major compaction 的示例。在這個示例中,我們已經傳遞了一個 region 名字給 major_compact 命令來僅僅在一臺單獨的 region 上調用 major compaction。它也可能在一張表中的所有 region 上運行 major compaction,通過傳遞表名給該命令。major_compact 命令為 major compaction 給指定的表或 region 排隊;但是通過 region 服務器托管它們,這些將在后臺執行。
正如我們在早前提到的,你或許僅僅想在一個低負載時期手動執行 major compaction。這可以很容易的通過一個定時任務調用 major_compact 來實現。
另外一個調用 major compaction 的方法就是使用 org.apache.hadoop.hbase.client.HBaseAdmin 類提供的 majorCompact API。在 Java 中非常容易調用這個 API。因此你可以從 Java 中管理復雜的 major compaction 調度。
通常一個 HBase 表從一個單獨的 region 開始。盡管如此,因為數據保持增長和 region 達到了它配置的最大值,它自動分成兩份,以至于它們能處理更多的數據。以下圖表展示了一個 HBase region 拆分:
這是 HBase region 拆分的默認行為。這個原理在大多數情況下工作的很好,然而有遇到問題的情況,比如 split/ compaction 風暴問題。
隨著統一的數據分布和增長,最后在表中的所有 region 都需要在同一時間拆分。緊接著一個拆分,壓縮將在子 region 運行以重寫他們的數據到獨立的文件中。這會引起大量的磁盤 I/O 讀寫和網絡流量。
為了避免這樣的情況,你可以關閉自動拆分和手動調用它。因為你可以控制在何時調用拆分,它可以幫助擴展 I/O 負載。另一個優勢是,手動拆分可以讓你有更好的 regions 控制,幫助你跟蹤和解決 region 相關的問題。
在這方面,我將描述怎樣關閉自動 region 拆分和手動調用它。
使用你啟動集群的用戶登錄進你的 HBase master 服務器。
為了關閉自動 region 拆分和手動調用它,遵循以下步驟:
在 hbase-site.xml 文件中加入以下代碼:
$ vi $HBASE_HOME/conf/hbase-site.xml<property><name>hbase.hregion.max.filesize</name><value>107374182400</value></property>
在集群中同步這些變更并重啟 HBase。
使用上述設置,region 拆分將不會發生直到 region 的大小到達了配置的 100GB 閥值。你將需要在選擇的 region 上明確調用它。
為了通過 HBase Shell 運行一個 region 拆分,使用以下命令:
$ echo "split 'hly_temp,,1327118470453.5ef67f6d2a792fb0bd737863dc00b6a7.'" | $HBASE_HOME/bin/hbase shell HBase Shell; enter 'help<RETURN>' for list of supported commands. Type "exit<RETURN>" to leave the HBase Shell Version 0.92.0, r1231986, Tue Jan 17 02:30:24 UTC 2012split 'hly_temp,,1327118470453.5ef67f6d2a792fb0bd737863dc00b6a7.'0 row(s) in 1.6810 seconds
hbase.hregion.max.filesize 屬性指定了最大的 region 大小(bytes)。默認,值是 1GB( HBase 0.92 之前的版本是 256MB)。這意味著當一個 region 超過這個大小,它將拆分成兩個。在步驟 1 中我們設置 region 最大值為 100GB,這是一個非常高的數字。
因為拆分不會發生直到超過了 100GB 的邊界,我們需要明確的調用它。在步驟 4,我們在一個指定的 region 上使用 split 命令通過 HBase Shell 調用拆分。
不要忘記拆分大的 region。一個 region 在 HBase 是基礎的數據分布和負載單元。Region 應該在低負載時期被拆分成合適的大小。
換句話說;太多的拆分不好,在一臺 region 服務器上有太多的拆分會降低它的性能。
在手動拆分 region 之后,你或許想觸發 major compaction 和負載均衡。
我們在前面的設置會引起整個集群有一個默認的 100GB 的region 最大值。除了改變整個集群,當在創建一張表的時候,也可以在一個列簇的基礎上指定 MAX_FILESIZE 屬性。
$ hbase> create 't1', {NAME => 'cf1', MAX_FILESIZE => '107374182400'}
像 major compaction,你也可以使用 org.apache.hadoop.hbase.client.HBaseAdmin 類提供的 split API。
關于“HBase如何管理以及性能調優”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。