您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)HBase如何管理以及性能調(diào)優(yōu),小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
因為 HBase 運(yùn)行在 JVM,JVM 的 Garbage Collection(GC) 設(shè)置對于 HBase 流暢的運(yùn)行,更高的性能是非常重要的,除了配置 HBase 堆設(shè)置的指導(dǎo)方針之外。有 HBase 進(jìn)程輸出到它們的 GC 日志中是同樣重要的,并且它們基于 GC 日志的輸出調(diào)整 JVM 設(shè)置。
我將描述最重要的 HBase JVM 堆設(shè)置,也描述怎樣是它生效以及理解 GC 日志,在這方面。我將覆蓋一些指導(dǎo)方針來調(diào)整 HBase 的 Java GC 設(shè)置。
登陸你的 HBase region 服務(wù)器。
以下被建議用于 Java GC 和 HBase 堆設(shè)置:
通過編輯 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"
把以下代碼加入來比默認(rèn)更早的開始 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 堆內(nèi)存大小。默認(rèn),HBase 使用 1GB 的堆,這對于現(xiàn)代的機(jī)器來說太低了。對于 HBase 來說,比 4GB 更大是好的。我們建議 8GB 或更大,但是低于 16 GB。
在步驟 2 中,我們是 JVM 日志生效,使用這個設(shè)置,你可以獲取 region 服務(wù)器的 JVM 日志,和我們在步驟 5 中展示的類似。關(guān)于 JVM 內(nèi)存分配和垃圾回收的基礎(chǔ)知識是被要求的,為了明白日志輸出。以下是 JVM 分代垃圾收集系統(tǒng)的圖表:
這里有 3 個堆分代:Perm(或是 Permanent)代【永久代】,Old Generation 代【老年代】,和 Young 代【年輕代】。年輕代由三個獨(dú)立的空間組成,Eden 空間和兩個 survivor 空間,S0 和 S1。
通常,對象被分配在年輕代的 Eden 空間,如果一個分配失?。?strong>Eden 滿了),所有 java 線程停止,并且一個年輕代 GC(Minor GC)被調(diào)用。所有在年輕代存活的對象(Eden 和 S0 空間)被拷貝到 S1 空間。如果 S1 空間滿了,對象被拷貝(提升)到老年代。當(dāng)一個提升失敗,老年代被收集(Major/Full GC)。永久代和老年代通常一起被收集。永久代被用于在存放類和對象中定義的方法。
回到我們示例的步驟 5,上述選項產(chǎn)出的 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 發(fā)生的時間,相對于應(yīng)用的啟動時間。
collector 是 collector 用于 minor collection 的內(nèi)部名字
starting occupancy1 是年輕代在垃圾回收前的占用
ending occupancy1 是年輕代在垃圾回收后的占用
pause time1 是 minor collection 中斷的時間
starting occupancy3 是在垃圾回收前整個堆的占用
ending occupancy3 是在垃圾回收后整個堆的占用
pause time3 是整個垃圾回收的中斷時間,這包括 major collection。
[Time:] 解釋了花費(fèi)在垃圾收集的時間,用戶時間,系統(tǒng)時間,實際時間。
在步驟 5 中我們輸出的第一行表明了是一個 minor GC,中斷了 JVM 0.0764200 秒,它已經(jīng)把年輕代的空間從 14.8MB 降低到 1.6MB。
接著,我們看看 CMS GC 日志,HBase 使用 CMS GC 作為它默認(rèn)的老年代垃圾回收器。
CMS GC 執(zhí)行以下步驟:
初始化標(biāo)記
并發(fā)標(biāo)記
重復(fù)標(biāo)記
并發(fā)休眠
CMS 僅僅在它初始化標(biāo)記和重復(fù)標(biāo)記的階段中斷應(yīng)用進(jìn)程。在并發(fā)標(biāo)記和睡眠階段,CMS 線程隨著應(yīng)用線程一起運(yùn)行。
在該示例的第二行表明了 CMS 初始化標(biāo)記花費(fèi)了 0.0100050 秒,并發(fā)標(biāo)記花費(fèi)了 6.496 秒。注意,并發(fā)標(biāo)記,Java 不會被中斷。
在 GC 日志的早期屏幕截圖中,在行開始于 1441.435: [GC[YG occupancy:…] 的地方有一個中斷。這里的中斷是 0.0413960 秒,用于重復(fù)標(biāo)記堆。之后,你可以看到睡眠開始了。CMS 睡眠花費(fèi)了 3.446 秒,但是堆大小在這里沒有變化太多(它繼續(xù)占據(jù)大約 150MB)。
這里的調(diào)整點是使得所有的中斷時間更低。為了保持中斷時間更低,你需要使用 -XX:NewSize 和 -XX:MaxNewSize JVM 參數(shù)調(diào)整年輕代空間大小,為了將它們設(shè)置為相對較小的值(比如,調(diào)高幾百 MB)。如果服務(wù)器有更多的 CPU 資源,我們建議通過設(shè)置 -XX:+UseParNewGC 選項使用 Parallel New Collector。你或許也想為你的年輕代調(diào)整 parallel GC 線程數(shù)量,通過 -XX:ParallelGCThreads JVM 參數(shù)。
我們建議加入上述設(shè)置到 HBASE_REGIONSERVER_OPTS 變量中,代替 hbase-env.sh 文件中的 HBASE_OPTS 變量。HBASE_REGIONSERVER_OPTS 僅僅影響 region 服務(wù)器的進(jìn)程,這非常好,因為 HBase master 既不處理重型任務(wù)也不參與數(shù)據(jù)處理。
對于老年代來說, concurrent collection (CMS) 通常不能被加速,但是它可以更早的開始。當(dāng)分配在老年代的空間比率超過了一個閥值,CMS 開始運(yùn)行。這個閥值是被收集器自動計算的。對于有些情況,特別是在加載期間,如果 CMS 開始的太晚,HBase 或許會直接進(jìn)行 full garbage collection。為了避免這個,我們建議設(shè)置 -XX:CMSInitiatingOccupancyFraction JVM 參數(shù)來精確指定在多少百分比 CMS 應(yīng)該被開始,正如我們在步驟 3 中做的那樣。在 百分之 60 或 70 開始是一個好的實踐。當(dāng)老年代使用 CMS,默認(rèn)的年輕代 GC 將被設(shè)置成 Parallel New Collector。
如果你之前使用的是 HBase 0.92 版本,考慮使用 MemStore-Local 分配 Buffer 來預(yù)防老年代堆碎片,在頻繁寫的負(fù)載下:
$ vi $HBASE_HOME/conf/hbase-site.xml <property> <name>hbase.hregion.memstore.mslab.enabled</name> <value>true</value> </property>
這個特性在 HBase 0.92 中是默認(rèn)開啟的。
HBase 另外一個最重要的特性就是使用壓縮。它是非常重要的,因為:
壓縮降低從 HDFS 讀寫的字節(jié)數(shù)
節(jié)約磁盤空間
當(dāng)從一個遠(yuǎn)程服務(wù)器獲取數(shù)據(jù)的時候,提升了網(wǎng)絡(luò)帶寬的效率
HBase 支持 GZip 和 LZO 格式,我的建議是使用 LZO 壓縮算法,因為它解壓數(shù)據(jù)快并且 CPU 使用率低。更好的壓縮比是系統(tǒng)的首選,你應(yīng)該考慮 GZip。
不幸的是,HBase 不能使用 LZO,因為 license 問題。HBase 是 Apache-licensed,然而 LZO 是 GPL-licensed。因此,我們需要自己安裝 LZO。我們將使用 hadoop-lzo 庫,給 Hadoop 帶來了變形的 LZO 算法。
在這方面,我們將描述怎樣安裝 LZO 和怎樣配置 HBase 使用 LZO 壓縮。
確保在 hadoop-lzo 被構(gòu)建的機(jī)器上 Java 安裝了。Apache Ant 被要求用來從源碼構(gòu)建 hadoop-lzo。通過運(yùn)行一下命令來安裝 Ant:
$ sudo apt-get -y install ant
集群中的所有節(jié)點需要有原生的 LZO 庫被安裝。你可以通過使用以下命令安裝:
$ sudo apt-get -y install liblzo2-dev
我們將使用 hadoop-lzo 庫來給 HBase 添加 LZO 壓縮支持:
從 https://github.com/toddlipcon/hadoop-lzo 獲取最新的 hadoop-lzo 源碼
從源碼構(gòu)建原生的 hadoop-lzo 庫。依賴于你的 OS,你應(yīng)該選擇構(gòu)建 32-bit 或 64-bit 的二進(jìn)制包。比如,為了構(gòu)建 32-bit 二進(jìn)制包,運(yùn)行以下命令:
$ export JAVA_HOME="/usr/local/jdk1.6"$ export CFLAGS="-m32"$ export CXXFLAGS="-m32"$ cd hadoop-lzo$ ant compile-native$ ant jar
這些命令將創(chuàng)建 hadoop-lzo/build/native 目錄和 hadoop-lzo/build/hadoop-lzo-x.y.z.jar 文件。為了構(gòu)建 64-bit 二進(jìn)制包,你需要改變 CFLAGS 和 CXXFLAGS 成 m64。
拷貝構(gòu)建的包到你master 節(jié)點的 $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 使用一個工具來測試壓縮是否被正確設(shè)置了。使用這個工具來在集群中的每個節(jié)點上測試 LZO 設(shè)置。如果一切都正確無誤的配置了,你將得到成功的輸出:
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 壓縮創(chuàng)建一個表來測試配置,并在 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 時間。默認(rèn)是時間是 86400000,即一天。我們在步驟 1 中把它設(shè)置為 0,是禁止自動的 major compaction。這將預(yù)防 major compaction 在繁忙加載時間運(yùn)行,比如當(dāng) MapReduce 任務(wù)正運(yùn)行在 HBase 集群上。
換句話說, major compaction 被要求來幫助提升性能。在步驟 4 中,我們已經(jīng)展示了通過 HBase Shell 怎樣在一個特別的 region 上手動觸發(fā) major compaction 的示例。在這個示例中,我們已經(jīng)傳遞了一個 region 名字給 major_compact 命令來僅僅在一臺單獨(dú)的 region 上調(diào)用 major compaction。它也可能在一張表中的所有 region 上運(yùn)行 major compaction,通過傳遞表名給該命令。major_compact 命令為 major compaction 給指定的表或 region 排隊;但是通過 region 服務(wù)器托管它們,這些將在后臺執(zhí)行。
正如我們在早前提到的,你或許僅僅想在一個低負(fù)載時期手動執(zhí)行 major compaction。這可以很容易的通過一個定時任務(wù)調(diào)用 major_compact 來實現(xiàn)。
另外一個調(diào)用 major compaction 的方法就是使用 org.apache.hadoop.hbase.client.HBaseAdmin 類提供的 majorCompact API。在 Java 中非常容易調(diào)用這個 API。因此你可以從 Java 中管理復(fù)雜的 major compaction 調(diào)度。
通常一個 HBase 表從一個單獨(dú)的 region 開始。盡管如此,因為數(shù)據(jù)保持增長和 region 達(dá)到了它配置的最大值,它自動分成兩份,以至于它們能處理更多的數(shù)據(jù)。以下圖表展示了一個 HBase region 拆分:
這是 HBase region 拆分的默認(rèn)行為。這個原理在大多數(shù)情況下工作的很好,然而有遇到問題的情況,比如 split/ compaction 風(fēng)暴問題。
隨著統(tǒng)一的數(shù)據(jù)分布和增長,最后在表中的所有 region 都需要在同一時間拆分。緊接著一個拆分,壓縮將在子 region 運(yùn)行以重寫他們的數(shù)據(jù)到獨(dú)立的文件中。這會引起大量的磁盤 I/O 讀寫和網(wǎng)絡(luò)流量。
為了避免這樣的情況,你可以關(guān)閉自動拆分和手動調(diào)用它。因為你可以控制在何時調(diào)用拆分,它可以幫助擴(kuò)展 I/O 負(fù)載。另一個優(yōu)勢是,手動拆分可以讓你有更好的 regions 控制,幫助你跟蹤和解決 region 相關(guān)的問題。
在這方面,我將描述怎樣關(guān)閉自動 region 拆分和手動調(diào)用它。
使用你啟動集群的用戶登錄進(jìn)你的 HBase master 服務(wù)器。
為了關(guān)閉自動 region 拆分和手動調(diào)用它,遵循以下步驟:
在 hbase-site.xml 文件中加入以下代碼:
$ vi $HBASE_HOME/conf/hbase-site.xml<property><name>hbase.hregion.max.filesize</name><value>107374182400</value></property>
在集群中同步這些變更并重啟 HBase。
使用上述設(shè)置,region 拆分將不會發(fā)生直到 region 的大小到達(dá)了配置的 100GB 閥值。你將需要在選擇的 region 上明確調(diào)用它。
為了通過 HBase Shell 運(yùn)行一個 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)。默認(rèn),值是 1GB( HBase 0.92 之前的版本是 256MB)。這意味著當(dāng)一個 region 超過這個大小,它將拆分成兩個。在步驟 1 中我們設(shè)置 region 最大值為 100GB,這是一個非常高的數(shù)字。
因為拆分不會發(fā)生直到超過了 100GB 的邊界,我們需要明確的調(diào)用它。在步驟 4,我們在一個指定的 region 上使用 split 命令通過 HBase Shell 調(diào)用拆分。
不要忘記拆分大的 region。一個 region 在 HBase 是基礎(chǔ)的數(shù)據(jù)分布和負(fù)載單元。Region 應(yīng)該在低負(fù)載時期被拆分成合適的大小。
換句話說;太多的拆分不好,在一臺 region 服務(wù)器上有太多的拆分會降低它的性能。
在手動拆分 region 之后,你或許想觸發(fā) major compaction 和負(fù)載均衡。
我們在前面的設(shè)置會引起整個集群有一個默認(rèn)的 100GB 的region 最大值。除了改變整個集群,當(dāng)在創(chuàng)建一張表的時候,也可以在一個列簇的基礎(chǔ)上指定 MAX_FILESIZE 屬性。
$ hbase> create 't1', {NAME => 'cf1', MAX_FILESIZE => '107374182400'}
像 major compaction,你也可以使用 org.apache.hadoop.hbase.client.HBaseAdmin 類提供的 split API。
關(guān)于“HBase如何管理以及性能調(diào)優(yōu)”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。