HBase最佳化實戰

loveheping發表於2018-08-31

轉載自:https://mp.weixin.qq.com/s/3AAy2LIQPxWivfFVrk4iew

背景

Datastream一直以來在使用HBase分流日誌,每天的資料量很大,日均大概在80億條,10TB的資料。對於像Datastream這種資料量巨大、對寫入要求非常高,並且沒有複雜查詢需求的日誌系統來說,選用HBase作為其資料儲存平臺,無疑是一個非常不錯的選擇。

HBase是一個相對較複雜的分散式系統,併發寫入的效能非常高。然而,分散式系統從結構上來講,也相對較複雜,模組繁多,各個模組之間也很容易出現一些問題,所以對像HBase這樣的大型分散式系統來說,最佳化系統執行,及時解決系統執行過程中出現的問題也變得至關重要。正所謂:“你”若安好,便是晴天;“你”若有恙,我便沒有星期天。

 

歷史現狀

HBase交接到我們團隊手上時,已經線上上執行有一大段時間了,期間也偶爾聽到過系統不穩定的、時常會出現一些問題的言論,但我們認為:一個能被大型網際網路公司廣泛採用的系統(包括Facebook,twitter,淘寶,小米等),其在效能和可用性上是毋庸置疑的,何況像Facebook這種公司,是在經過嚴格選型後,放棄了自己開發的Cassandra系統,用HBase取而代之。既然這樣,那麼,HBase的不穩定、經常出問題一定有些其他的原因,我們所要做的,就是找出這些HBase的不穩定因素,還HBase一個“清白”。“查案”之前,先來簡單回顧一下我們接手HBase時的現狀(我們運維著好幾個HBase叢集,這裡主要介紹問題最多那個叢集的調優):

名稱

數量

備註

伺服器數量

17

配置不同,HBase、HDFS都部署在這些機器上

表數量

30+

只有部分表的資料量比較大,其他基本沒多少資料

Region數量

600+

基本上都是資料量較大的表劃分的region較多

請求量

50000+

伺服器請求分佈極其不均勻

應用反應經常會過段時間出現資料寫入緩慢,導致應用端資料堆積現象,是否可以透過增加機器數量來解決?

其實,那個時候,我們本身對HBase也不是很熟悉,對HBase的瞭解,也僅僅在做過一些測試,瞭解一些效能,對內部結構,實現原理之類的基本上都不怎麼清楚。於是剛開始幾天,各種問題,每天晚上拉著一男一起摸索,順利的時候,晚上8,9點就可以暫時搞定線上問題,更多的時候基本要到22點甚至更晚(可能那個時候流量也下去了),透過不斷的摸索,慢慢了解HBase在使用上的一些限制,也就能逐漸解決這一系列過程中發現的問題。後面挑幾個相對比較重要,效果較為明顯的改進點,做下簡單介紹。

 

調優

首先根據目前17臺機器,50000+的QPS,並且觀察磁碟的I/O利用率和CPU利用率都相當低來判斷:當前的請求數量根本沒有達到系統的效能瓶頸,不需要新增機器來提高效能。如果不是硬體資源問題,那麼效能的瓶頸究竟是什麼?

 

Rowkey設計問題

現象 

開啟HBase的Web端,發現HBase下面各個RegionServer的請求數量非常不均勻,第一個想到的就是HBase的熱點問題,具體到某個具體表上的請求分佈如下:

HBase最佳化實戰

HBase表請求分佈


上面是HBase下某張表的region請求分佈情況,從中我們明顯可以看到,部分region的請求數量為0,而部分的請求數量可以上百萬,這是一個典型的熱點問題。

 

原因

HBase出現熱點問題的主要原因無非就是rowkey設計的合理性,像上面這種問題,如果rowkey設計得不好,很容易出現,比如:用時間戳生成rowkey,由於時間戳在一段時間內都是連續的,導致在不同的時間段,訪問都集中在幾個RegionServer上,從而造成熱點問題。

 

解決

知道了問題的原因,對症下藥即可,聯絡應用修改rowkey規則,使rowkey資料隨機均勻分佈,效果如下:

HBase最佳化實戰

Rowkey重定義後請求分佈

 

建議

對於HBase來說,rowkey的範圍劃定RegionServer,每一段rowkey區間對應一個RegionServer,我們要 保證每段時間內的rowkey訪問都是均勻的 ,所以我們在設計的時候, 儘量要以hash或者md5等開頭來組織rowkey

 

Region重分佈

現象

HBase的叢集是在不斷擴充套件的,分散式系統的最大好處除了效能外,不停服橫向擴充套件也是其中之一,擴充套件過程中有一個問題:每次擴充套件的機器的配置是不一樣的,一般,後面新加入的機器效能會比老的機器好,但是後面加入的機器經常被分配很少的region,這樣就造成了資源分佈不均勻,隨之而來的就是效能上的損失,如下:

HBase最佳化實戰

HBase各個RegionServer請求


上圖中我們可以看到,每臺RegionServer上的請求極為不均勻,多的好幾千,少的只有幾十。

 

原因

資源分配不均勻,造成部分機器壓力較大,部分機器負載較低,並且部分Region過大過熱,導致請求相對較集中。

 

解決

遷移部分老的RegionServer上的region到新加入的機器上,使每個RegionServer的負載均勻。透過split切分部分較大region,均勻分佈熱點region到各個RegionServer上。

HBase最佳化實戰

HBase Region請求分佈


對比前後兩張截圖我們可以看到,Region總數量從1336增加到了1426,而增加的這90個region就是透過split切分大的region得到的。而對region重新分佈後,整個HBase的效能有了大幅度提高。

 

建議

Region遷移的時候不能簡單開啟自動balance ,因為balance主要的問題是不會根據表來進行balance,HBase的自動balance只會根據每個RegionServer上的Region數量來進行balance,所以自動balance可能會造成同張表的region會被集中遷移到同一個臺RegionServer上,這樣就達不到分散式的效果。

基本上,新增RegionServer後的region調整,可以手工進行,儘量使表的Region都平均分配到各個RegionServer上,另外一點,新增的RegionServer機器,配置最好與前面的一致,否則資源無法更好利用。

對於過大,過熱的region,可以透過切分的方法生成多個小region後均勻分佈(注意:region切分會觸發major compact操作,會帶來較大的I/O請求,請務必在業務低峰期進行)。

 

HDFS寫入超時

現象

HBase寫入緩慢,檢視HBase日誌,經常有慢日誌如下:



WARN org.apache.hadoop.ipc.HBaseServer- (responseTooSlow): {

"processingtimems"

:

36096

"call"

:

"multi(org.apache.hadoop.hbase.client.MultiAction@7884377e), rpc version=1, client version=29, methodsFingerPrint=1891768260"

"client"

:

"xxxx.xxx.xxx.xxxx:44367"

"starttimems"

:

1440239670790

"queuetimems"

:

42081

"class"

:

"HRegionServer"

"responsesize"

:


"method"

:

"multi"

}

並且伴有HDFS建立block異常如下:



INFO org.apache.hadoop.hdfs.DFSClient - Exception 

in

 createBlockOutputStream

org.apache.hadoop.hdfs.protocol.HdfsProtoUtil.vintPrefixed(HdfsProtoUtil.java:171)
org.apache.hadoop.hdfs.DFSOutputStream $DataStreamer .createBlockOutputStream(DFSOutputStream.java:1105)
org.apache.hadoop.hdfs.DFSOutputStream $DataStreamer .nextBlockOutputStream(DFSOutputStream.java:1039)
org.apache.hadoop.hdfs.DFSOutputStream $DataStreamer .run(DFSOutputStream.java:487)

一般地,HBase客戶端的寫入到RegionServer下某個region的memstore後就返回,除了網路外,其他都是記憶體操作,應該不會有長達30多秒的延遲,外加HDFS層丟擲的異常,我們懷疑很可能跟底層資料儲存有關。

 

原因

定位到可能是HDFS層出現了問題,那就先從底層開始排查,發現該臺機器上10塊盤的空間利用率都已經達到100%。按理說,作為一個成熟的分散式檔案系統,對於部分資料盤滿的情況,應該有其應對措施。的確,HDFS本身可以設定資料盤預留空間,如果部分資料盤的預留空間小於該值時,HDFS會自動把資料寫入到另外的空盤上面,那麼我們這個又是什麼情況?

最終透過多方面的溝通確認,發現了主要原因:我們這批機器,在上線前SA已經經過處理,每塊盤預設預留100G空間,所以當透過df命令檢視盤使用率為100%時,其實盤還有100G的預留空間,而HDFS層面我們配置的預留空間是50G,那麼問題就來了:HDFS認為盤還有100G空間,並且多於50G的預留,所以資料可以寫入本地盤,但是系統層面卻禁止了該寫入操作,從而導致資料寫入異常。

 

解決

解決的方法可以讓SA釋放些空間出來便於資料寫入。當然,最直接有效的就是把HDFS的預留空間調整至100G以上,我們也正是這樣做的,透過調整後,異常不再出現,HBase層面的slow log也沒有再出現。同時我們也開啟了HDFS層面的balance,使資料自動在各個伺服器之間保持平衡。

 

建議

磁碟滿了導致的問題很難預料,HDFS可能會導致部分資料寫入異常,MySQL可能會出現直接當機等等,所以最好的辦法就是: 不要使盤的利用率達到100%

 

網路拓撲

現象

透過rowkey調整,HDFS資料balance等操作後,HBase的確穩定了許多,在很長一段時間都沒有出現寫入緩慢問題,整體的效能也上漲了很多。但時常會隔一段時間出現些slow log,雖然對整體的效能影響不大,但效能上的抖動還是很明顯。

 

原因

由於該問題不經常出現,對系統的診斷帶來不小的麻煩,排查了HBase層和HDFS層,幾乎一無所獲,因為在大多數情況下,系統的吞吐量都是正常的。透過指令碼收集RegionServer所在伺服器的系統資源資訊,也看不出問題所在,最後懷疑到系統的物理拓撲上,HBase叢集的最大特點是資料量巨大,在做一些操作時,很容易把物理機的千兆網路卡都吃滿,這樣如果網路拓撲結構存在問題,HBase的所有機器沒有部署在同一個交換機上,上層交換機的進出口流量也有可能存在瓶頸。網路測試還是挺簡單的,直接ping就可以,我們得到以下結果:共17臺機器,只有其中一臺的延遲存在問題,如下:

HBase最佳化實戰

網路延遲測試:Ping結果


同一個區域網內的機器,延遲達到了毫秒級別,這個延遲是比較致命的,因為分散式儲存系統HDFS本身對網路有要求,HDFS預設3副本存在不同的機器上,如果其中某臺機器的網路存在問題,這樣就會影響到該機器上儲存副本的寫入,拖慢整個HDFS的寫入速度。

 

解決

網路問題,聯絡機房解決,機房的反饋也驗證了我們的想法:由於HBase的機器後面進行了擴充套件,後面加入的機器有一臺跟其他機器不在同一個交換機下,而這臺機器正是我們找出的有較大ping延時這臺,整個HBase物理結構如下:

HBase最佳化實戰

HBase物理拓撲結構


跟機房協調,調整機器位置,使所有的HBase機器都位於同一個交換機下,問題迎刃而解。

 

建議

對於分散式大流量的系統,除了系統本身,物理機的部署和流量規劃也相當重要,儘量使叢集中所有的機器位於相同的交換機下(有容災需求的應用除外),叢集較大,需要跨交換機部署時,也要充分考慮交換機的出口流量是否夠用,網路硬體上的瓶頸診斷起來相對更為困難。

 

JVM引數調整

解決了網路上面的不穩定因素,HBase的效能又得到進一步的提高,隨之也帶來另外的問題。

現象

根據應用反應,HBase會階段性出現效能下降,導致應用資料寫入緩慢,造成應用端的資料堆積,這又是怎麼回事?經過一系列改善後HBase的系統較之以前有了大幅度增長,怎麼還會出現資料堆積的問題?為什麼會階段性出現?

HBase最佳化實戰


從上圖看,HBase平均流量QPS基本能達到12w,但是每過一段時間,流量就會下降到接近零點,同時這段時間,應用會反應資料堆積。

 

原因

這個問題定位相對還是比較簡單,結合HBase的日誌,很容易找到問題所在:



org.apache.hadoop.hbase.util.Sleeper - We slept 

41662

ms instead 

of

 

3000

ms, this 

is

 likely due 

to

 a 

long

 garbage collecting pause 

and

 it

's usually bad


透過上述日誌,基本上可以判定是HBase的某臺RegionServer出現GC問題,導致了服務在很長一段時間內禁止訪問。

HBase透過一系列的調整後,整個系統的吞吐量增加了好幾倍,然而JVM的堆大小沒有進行相應的調整,整個系統的記憶體需求變大,而虛擬機器又來不及回收,最終導致出現Full GC。

 

解決

GC問題導致HBase整個系統的請求下降,透過適當調整JVM引數的方式,解決HBase RegionServer的GC問題。

 

建議

對於HBase來說,本身不存在單點故障,即使宕掉1,2臺RegionServer,也只是使剩下幾臺的壓力有所增加,不會導致整個叢集服務能力下降很多。但是,如果其中某臺RegionServer出現Full GC問題,那麼這臺機器上所有的訪問都會被掛起,客戶端請求一般都是batch傳送的,rowkey的隨機分佈導致部分請求會落到該臺RegionServer上,這樣該客戶端的請求就會被阻塞,導致客戶端無法正常寫資料到HBase。所以,對於HBase來說,當機並不可怕,但長時間的Full GC是比較致命的,配置JVM引數的時候,儘量要考慮避免Full GC的出現。

 

後記

經過前面一系列的最佳化,目前Datastream的這套HBase線上環境已經相當穩定,連續執行幾個月都沒有任何HBase層面由於系統效能不穩定導致的報警,平均效能在各個時間段都比較穩定,沒有出現過大幅度的波動或者服務不可用等現象。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31511218/viewspace-2213356/,如需轉載,請註明出處,否則將追究法律責任。

相關文章