百度智慧監控場景下的HBase實踐

AIOps智慧運維發表於2019-03-15

作者簡介    張洋洋    百度高階研發工程師

負責百度智慧運維產品(Noah)的分散式時序資料庫和通用配額管理平臺的設計研發工作,在分散式儲存和配額管理方向有廣泛的實踐經驗。


乾貨概覽

透過百度大規模時序資料儲存系列文章的介紹,想必讀者對百度智慧監控系統Noah的TSDB不再陌生,它主要用來儲存Noah監控系統的時序指標資料,包括但不限於硬體和軟體的可用性指標、資源使用率指標和效能指標等。如《百度大規模時序資料儲存(二)|儲存選型及資料模型設計》文章所述, Noah-TSDB是基於HBase為底層儲存的基礎上自主研發的,其優秀的效能離不開HBase的貢獻。今天主要聊聊在百度智慧監控場景下的HBase相關實踐經驗,先簡單介紹一下HBase。

HBase架構簡介

HBase是一個基於Java、開源的、非關係型的、面向列儲存的分散式可擴充套件的大資料儲存資料庫。HBase的叢集主要由HMater和RegionServer兩種角色組成,底層以HDFS作為儲存設施,叢集由Zookeeper協助管理。其架構如下圖所示:

百度智慧監控場景下的HBase實踐

圖1  HBase架構圖

簡單介紹一下HBase中相關元件的作用:

  •   HMaster  

HMaster 是整個叢集的大腦,負責資料表的操作、叢集的負載均衡和故障恢復等叢集管理工作。

  •   RegionServer  

HBase 將表以行為單位劃分成許多片段,每個片段稱為一個 Region。這些Region被分配到RegionServer進行管理。在讀寫流程中,定位到資料所在RegionServer後,Client與RegionServer直接互動進行資料的讀寫。

  •   Zookeeper  

HBase作為一個大規模的分散式系統,Zookeeper的作用是至關重要的。首先Zookeeper作為HMaster HA解決方案,保證了至少有一個HMaster處於工作狀態。其次Zookeeper透過心跳機制探活RegionServer,當RegionServer故障時及時通知HMaster進行故障處理工作。最後Zookeeper儲存了維護全域性元資訊的META表的路徑,Client第一次與HBase叢集互動時,需要透過META表來獲取目標資料所在的RegionServer。

上面簡單介紹了HBase的架構和各元件的基本資訊,下面和大家分享一下在百度最大規模時序資料庫的場景下使用HBase時遇到的幾個典型問題和最佳化方案。

熱點問題

大家都知道木桶效應,對於TSDB系統來說,熱點Region所在的RegionServer就是影響整個”水桶”容量最短的那塊木板。理想情況下HBase 中所有的請求應該均勻的分佈在所有RgionServer的所有Region 上,當個別Region收到的讀寫請求數量大幅超過其它的Region,它所在的Region就有可能成為熱點。

百度智慧監控場景下的HBase實踐

圖2  RegionServer資訊(此圖來源網路非百度實際資料)

Noah-TSDB初期曾遇到監控後設資料表設計不合理導致熱點的問題。當時研發同學收到Noah-TSDB寫入模組佇列堵塞的業務報警,從Noah監控系統上看到同時間段訪問HBase異常明顯增長。HBase中的個別RegionServer頻繁進行GC,網路 I/O 和磁碟 I/O 密集,操作佇列中待執行的請求堆積嚴重,負載明顯高於其它的RegionServer。檢視異常RegionServer的日誌發現大量請求訪問的是同一個Region:”tsdb-meta,*** 1.”。初步定位是由於該Region負載過高,導致它所在的RegionServer成為熱點,進而導致系統的吞吐量下降,上游寫入模組請求堆積。

tsdb-meta是用來儲存監控指標的名稱、週期等元資訊的表,表中紅色填充的行代表其擁有資料量超過正常水平的,表結構如下:

表1  原始tsdb-meta表

百度智慧監控場景下的HBase實踐

分析上面的儲存結構,我們可以知道:

  1. 同一個監控物件(namespace)的監控指標元資訊將會儲存在 HBase 表的同一行。

  2. 不同監控物件的指標數量不同,將導致行的大小不均勻。

  3. HBase中資料分片是以行為單位,每行的資料儲存在同一個Region中,當某一行儲存的監控指標數量遠大於正常水平時,該行就有可能成為熱點。

綜上所述,當個別監控物件擁有的監控指標個數過多時,tsdb-meta可能會出現熱點問題。同時經我們驗證發現,成為熱點的監控物件擁有的監控指標的數量大約是正常水平的20倍左右,進一步確認了故障原因。

定位到根因後,我們決定從兩個方面來著手解決這個問題。一方面,定期統計監控物件擁有的指標個數,及時發現由於監控配置異常和不合理使用導致的個別監控物件擁有的監控指標過多的問題。第二方面,對tsdb-meta表結構改造,將原來按列分佈的資料修改為按行展開平鋪,充分打平資料,利用HBase按行自動分片的機制來達到負載均衡的狀態。第一方面主要是從業務層面對不合理使用的情況進行人工干預。今天主要著重介紹第二方面。

  •   tsdb-meta表Schema改造  

前文大體介紹了表結構改造的思路,避免單行資料過大導致熱點問題。我們將監控物件和監控指標的名稱資訊一起作為行鍵,只保留一列用於儲存指標的其餘資訊,避免了因單行資料過大導致的熱點問題。

表2  最佳化後的tsdb-meta表

百度智慧監控場景下的HBase實踐

  •   預分割槽  

tsdb-meta表最佳化後,我們發現生產環境儲存資料的 tsdb-data表也存在熱點問題。tsdb-data是用來儲存監控指標數值的表,生產環境是按時間跨度進行分表,每兩天的資料儲存在一張表中。資料的行鍵由資料hash後的特徵變數ts_uid和時間基準timestamp_base組成,利用HBase儲存時按行鍵的字典順序排序的特點,將不同的監控指標的資料雜湊到不同的Region,相同監控物件的指標資料順序排列,達到最佳化查詢的效果。由於tsdb-data表的日常訪問量基數較大,當某個監控物件擁有的指標數量高於平均水平,那麼該監控物件的監控指標很大機率會被分配到相同的Region,導致該Region過大,進成為熱點,叢集會分裂過大的Region來維持負載均衡的狀態。頻繁的分裂操作會佔用大量資源,影響RegionServer的吞吐量。為解決因Region過大導致的熱點,我們採用對資料表進行預分割槽的方法。

在對tsdb-data表進行預分割槽時,我們發現只透過指定Region數量來實現預分割槽的效果並不理想,因為會出現實際寫入量與槽位分配不均的問題。HBase資料表是按照行鍵的位元組空間均勻劃分而不是按照實際儲存的資料量進行劃分。如下圖所示,圖中紅色方塊代表實際儲存的資料,白色的方塊代表無實際資料的行。

百度智慧監控場景下的HBase實踐

圖3  原始Region預分割槽

如上圖,雖然資料表已經按照行鍵的位元組空間劃分成3個Region了,但是明顯Region 3中實際儲存的資料量遠大於Region 1和Region 2。這種情況下Region 3有成為熱點的可能性。為了改善這種情況,Noah-TSDB結合了生產環境中的tsdb-data表按等間隔時間跨度分表的特點,決定參照歷史表的使用情況對新表進行預分割槽。根據生產環境實際產生的行鍵和預期的分割槽大小計算出Region分界值,然後根據分界值將表劃分成實際水位相近的Region,這樣雖然每個Region的槽位大小不一樣,但是每個Region實際儲存的數量是相當的,進一步降低產生熱點的風險。

百度智慧監控場景下的HBase實踐

圖4  最佳化後的Region預分割槽

如何合理的設定Region數量

在前文介紹的預分割槽策略中,除了需要參考生產環境的實際使用情況外還需要根據機器資源和分裂閾值等系統引數來預估合適的Region大小,Region大小確定後,我們可以預估出整體的Region數量。那麼如何判斷當前叢集是否能夠承載調整後的Region數量呢?如果Region的數量不合理有哪些危害呢?在討論Region數量對叢集的影響之前,我們先了解一些基礎知識:

  1. 在HBase的資料寫入流程中,資料是先寫到Memstore(寫快取)排序,然後非同步Flush追加到HFile中。一個Region中的多個列族對應多個Memstore,Memstore Flush的最小單位是Region。

  2. 當一個RegionServer中所有Memstore的大小總和達到閾值hbase.regionserver.global.memstore.upperLimit  *  hbase_heapsize會觸發Memstore Flush。根據 Memstore從大到小依次Flush,直至MemStore記憶體使用量低於閾值 hbase_heapsize * hbase.regionserver.global.memstore.lowerLimit。

  3. HBase 會定期Flush Memstore來保障Memstore不會長時間沒有持久化。為避免所有的MemStore在同一時間都進行Flush導致的問題,定期的Flush操作有隨機延時。

綜上可知,一方面由於同一個RegionServer共享Memstore,Region數量過多會導致Memstore Flush的頻率變快,產生的HFile變多,HBase持續的進行 Compaction,引發合併風暴。另一方面由於HBase定期Flush Memstore,每次執行 Flush需要將每個Region的每個列族對應的Memstore寫入檔案並存到HDFS, Region數量越多,每次需要一起處理的檔案數量就越大,即使存在隨機時延機制,短時間內檔案的建立和資料的遷移較多也會加大叢集負載,可能引起快照超時、客戶端超時和批次載入超時,降低TSDB系統效能。因此Region數量過多會降低系統吞吐量。

Region數量過少也會降低系統效能。當資料量不變的情況下,由於Region數量過少導致單個Region過大,每個Region處理的寫入請求數偏高,當Flush的速度慢慢被寫入速度追上並趕超時,就會堵塞寫入,影響RPC,進而影響HBase的整體寫入和查詢,降低系統的吞吐量。

Region數量設定不合理,會降低TSDB系統整體效能與可靠性,一般推薦的單個RegionServer管理的Region數量計算方法如下:

#{Region} = (RS memory)*(total memstore fraction)/((memstore size)*(# {column families}))

舉個例子,如果RegionServer的引數如下:

  1. Java Heap Size of HBase RegionServer in Bytes設定的是20G

  2. hbase.regionserver.global.memstore.upperLimit是0.4

  3. hbase.hregion.memstore.flush.size是128M

  4. 多個表的列族個數共2個

那麼 #{Region} = 20 * 1024 * 0.4/ (128 * 2) = 32。這個公式是在假設所有的Region都在以相同的速率寫的前提下,如果實際只有部分Region在寫入資料,結果可以根據比例、結合業務進行調整。例如Noah-TSDB的場景下,資料是按照時間分表,一般兩天的資料存在一張資料表中,資料的寫入都集中在最近的一張表,因此實際寫入活躍的Region數量遠小於Region的總數量,所以實際每個RegionServer管理的Region的數量大約是透過上述公式直接計算結果的3倍左右。

預估出整體的Region數量和單個RegionServer管理的Region數量後,就可以合理的進行容量規劃,在叢集調整的時候預估需要的機器資源。

總  結

上面就是今天介紹的全部內容了,給大家簡單分享了一些使用HBase的實踐經驗。其實在實際使用時我們也發現了HBase過重,運維成本較高等問題,也在持續的進行調研和架構升級,大家有什麼好的建議歡迎不吝賜教。另外文中如果有理解不到位或者偏差的地方,歡迎大家指正。

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

相關文章