溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

HBase如何管理以及性能調(diào)優(yōu)

發(fā)布時間:2021-12-08 16:31:00 來源:億速云 閱讀:144 作者:小新 欄目:云計算

這篇文章將為大家詳細(xì)講解有關(guān)HBase如何管理以及性能調(diào)優(yōu),小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

Java GC 和 HBase 堆設(shè)置

因為 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è)置。

準(zhǔn)備工作

登陸你的 HBase region 服務(wù)器

怎樣做

以下被建議用于 Java GC 和 HBase 堆設(shè)置:

  1. 通過編輯 hbase-env.sh 文件給 HBase 足夠大的堆大小。比如,以下片段給 HBase 配置一個 8000-MB 的堆:

    $ vi $HBASE_HOME/conf/hbase-env.shexport HBASE_HEAPSIZE=8000
  2. 通過以下命令使得 GC 日志生效:

    export HBASE_OPTS="$HBASE_OPTS -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/usr/local/hbase/logs/gc-hbase.log"
  3. 把以下代碼加入來比默認(rèn)更早的開始 Concurrent-Mark-Sweep GC(CMS)

    $ vi $HBASE_HOME/conf/hbase-env.shexport HBASE_OPTS="$HBASE_OPTS -XX:CMSInitiatingOccupancyFraction=60"
  4. 在集群中同步變更并重啟 HBase。

  5. 檢查輸出到指定日志文件中(/usr/local/hbase/logs/gc-hbase.log)的 GC 日志。GC 日志看起來像以下屏幕截圖:

HBase如何管理以及性能調(diào)優(yōu)

它怎樣工作

在步驟 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)的圖表:

HBase如何管理以及性能調(diào)優(yōu)

這里有 3 個堆分代:Perm(或是 Permanent)代【永久代】,Old Generation 代【老年代】,和 Young 代【年輕代】。年輕代由三個獨(dú)立的空間組成,Eden 空間和兩個 survivor 空間,S0S1。

通常,對象被分配在年輕代的 Eden 空間,如果一個分配失?。?strong>Eden 滿了),所有 java 線程停止,并且一個年輕代 GC(Minor GC)被調(diào)用。所有在年輕代存活的對象(EdenS0 空間)被拷貝到 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í)行以下步驟:

  1. 初始化標(biāo)記

  2. 并發(fā)標(biāo)記

  3. 重復(fù)標(biāo)記

  4. 并發(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 壓縮。

準(zhǔn)備工作

確保在 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 壓縮支持:

  1. 從 https://github.com/toddlipcon/hadoop-lzo 獲取最新的  hadoop-lzo 源碼

  2. 從源碼構(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。

  3. 拷貝構(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。

  4. 添加 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>
  5. 在集群中同步 $HBASE_HOME/conf 和 $HBASE_HOME/lib 目錄。

  6. 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
  7. 通過使用 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)度。

管理 region 拆分

通常一個 HBase  表從一個單獨(dú)的 region 開始。盡管如此,因為數(shù)據(jù)保持增長和 region 達(dá)到了它配置的最大值,它自動分成兩份,以至于它們能處理更多的數(shù)據(jù)。以下圖表展示了一個  HBase region 拆分:

HBase如何管理以及性能調(diào)優(yōu)

這是 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)用它。

準(zhǔn)備工作

使用你啟動集群的用戶登錄進(jìn)你的 HBase master 服務(wù)器。

怎樣做

為了關(guān)閉自動 region 拆分和手動調(diào)用它,遵循以下步驟:

  1. 在  hbase-site.xml 文件中加入以下代碼:

    $ vi $HBASE_HOME/conf/hbase-site.xml<property><name>hbase.hregion.max.filesize</name><value>107374182400</value></property>
  2. 在集群中同步這些變更并重啟 HBase。

  3. 使用上述設(shè)置,region 拆分將不會發(fā)生直到 region 的大小到達(dá)了配置的 100GB 閥值。你將需要在選擇的 region 上明確調(diào)用它。

  4. 為了通過 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é)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(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)容。

AI