58HBase平台實踐和應用—時序數據庫篇
- 2019 年 10 月 31 日
- 筆記
OpenTSDB是一個分佈式、可伸縮的時序數據庫,支持高達每秒百萬級的寫入能力,支持毫秒級精度的數據存儲,不需要降精度也可以永久保存數據。其優越的寫性能和存儲能力,得益於其底層依賴的HBase,HBase採用LSM樹結構存儲引擎加上分佈式的架構,提供了優越的寫入能力,底層依賴的完全水平擴展的HDFS提供了優越的存儲能力。
在58,OpenTSDB目前主要用於數據平台監控系統中相關性能指標的存儲查詢,58智能監控系統中回歸模型和分類模型原始明細數據存儲查詢,以及風鈴監控預警系統數據的存儲查詢等。
OpenTSDB架構:

OpenTSDB主要由以下幾部分組成:
(1)、Collector:負責從服務器上收集並通過telnet或http協議發送數據給TSD實例;
(2)、TSD實例:TSD是無狀態的服務,負責接收Collector發送過來的數據,並對外提供數據查詢服務,可以部署多個讀寫實例;
(3)、HBase集群:TSD接收到監控數據後,通過AsyncHbase將數據寫入到HBase,AsyncHbase是完全異步、非阻塞、線程安全的HBase客戶端,使用更少的線程、鎖以及內存,可以提供更高的吞吐量,特別對於大量的寫操作。
一、數據模型和存儲優化
1、數據模型
OpenTSDB採用按指標建模的方式,一個datapoint包含以下幾個部分:
(1)、metrics:指標名稱,例如sys.cpu.user;
(2)、timestamp:秒級或毫秒級的Unix時間戳,代表該時間點的具體時間;
(3)、tags:一個或多個標籤,也就是描述主體的不同的維度。Tag由TagKey和TagValue組成,TagKey就是維度,TagValue就是該維度的值;
(4)、該指標的值,目前只支持數值類型的值。
2、存儲優化
OpenTSDB對HBase深度依賴,並且根據HBase底層存儲結構的特性,做了很多巧妙的優化。
(1)、縮短rowkey的長度。OpenTSDB使用一個字典表tsdb-uid,將metrics和tag映射成3位整數的uid,存儲指標數據時按uid存儲,節省了大量存儲空間,同時提高了查詢效率。tsdb-uid表結構如下圖所示:

(2)、減少keyvalue的數量。OpenTSDB實際存儲數據的表為tsdb表,對於一小時內相同metrics和tags的datapoint,在tsdb表中OpenTSDB會合併成一行數據,並且更進一步,將所有列的數據會合併成一列,通過合併數據行和列減少了大量冗餘key的存儲,節省大量存儲空間。tsdb表結構如下圖所示:

(3)、並發寫優化。為了避免熱點問題,OpenTSDB支持在建數據存儲表時,設置分桶,當某一個metrics下數據點很多時,可以將寫壓力分散到多個桶中,避免了寫熱點的產生。
二、案例分享
1、數據平台監控系統
監控系統架構:

數據平台監控系統監控的相關組件包括:Hadoop、HBase、Kafka、Flume和Zookeeper等。由於TSD實例是無狀態的,我們部署了多個讀寫實例,對外通過域名進行數據讀寫分離,保證服務的高可用。採集的監控數據最終通過TSD實例存儲到HBase集群,並基於HBase的RSGroup機制進行物理隔離。由於OpenTSDB的可視化能力較弱,並且沒有報警功能,我們選擇了Grafana作為監控系統的可視化和報警模塊,Grafana支持多種數據源,OpenTSDB是支持的其中一個數據源,而且可視化效果非常好。
在我們的實際使用中,TSD單實例寫QPS最高到達了10萬+,存儲到HBase的監控數據量半年預估達到10T+,而支撐這一能力的後端HBase集群只用了5個節點,從而可以看出OpenTSDB強大的寫性能。
Grafana中RegionServer活躍handler線程數的可視化截圖:

2、58智能監控系統
58智能監控系統架構:

58智能監控系統中,OpenTSDB主要用於存儲網絡出口和業務的進出流量、集群和域名的訪問量、宏觀業務數據等的原始數據,並使用回歸模型按天預測流量變化趨勢,使用分類模型對實時流量做異常檢測。
以下是流量預測效果圖:

三、遇到的問題
在58智能監控系統和風鈴監控預警系統使用OpenTSDB時,我們遇到了一個相同的問題:
某個metrics在同一時間段內寫入了大量的datapoint,而且datapoint屬於不同的標籤組合,標籤基數達到百萬級,結果在查詢這一時段該metrics數據時,響應非常緩慢,甚至將HBase的RegionServer所有handler線程阻塞,導致TSD實例最終不可用,嚴重影響了用戶體驗,但是發現查詢其它時段該metrics的數據是沒有問題的。
問題分析:
OpenTSDB數據存儲表tsdb的rowkey結構:metrics+timestamp+tags,第一個是metrics,第二個是時間戳,第三個是tags,tags可能包含了多個標籤名稱和標籤值,而這些標籤之間是沒有特定順序的,比如tags可能取值為:{tk3=tv3,tk1=tv1,tk2=tv2,…},如下圖中tsdb表rowkey部分。在進行查詢時,查詢條件包括該metrics,查詢時間範圍包括了有查詢問題的時間段,查詢標籤取值為{tk2=tv2},如下圖查詢條件部分。在查詢的時候由於無法知道數據寫入時rowkey中標籤之間的順序,導致所有的OpenTSDB查詢都只能進行前綴查詢+filter,前綴查詢字段包括metrics和timestamp,而標籤匹配只能通過HBase的filter機制在RegionServer內存中進行過濾,如下圖紅色虛線部分。

而由於該查詢時間段內metrics寫入了大量標籤的數據,標籤量基數達到百萬級,datapoint更是達到上億,根據metrics+ts的前綴過濾後,需要在RegionServer內存中filter的標籤數據量達到百萬級,進行百萬級的數據量filter自然會導致查詢響應變慢了。
問題解決:
(1)、建tsdb表時設置預分桶存儲,提升並發查詢性能,但是由於已經在生產環境中,無法重建該表,該方案捨棄。
(2)、刪除多餘數據。經過和業務溝通,多餘入庫的這部分數據暫時不需要統計分析,可以刪除。考慮到在線刪除數據肯定會對線上業務造成干擾,並且考慮到Hbase的LSM存儲結構特性,最終採取在測試HBase集群刪除數據然後合併到在線集群的方式解決了該問題。
以下是整個刪除數據的操作流程,包括4個步驟:

①、在測試集群創建和在線集群相同表結構(包括分區信息)的tsdb表,修改hbase集群配置保證不要觸發minor compact和major compact。使用跨集群拷貝工具distcp將在線集群tsdb表的hfile文件拷貝到測試集群,最後將hfile通過bulkload工具加載到測試tsdb表中。
②、在測試環境部署一個tsdb實例,並開啟tsd.http.query.allow_delete=true,允許tsdb實例支持查詢的同時刪除對應記錄,最後根據要刪除的數據列表,執行查詢刪除操作。
③、通過distcp拷貝測試環境tsdb表的hfile到hbase在線集群,並執行bulkload操作導入正式的tsdb表。
④、對在線集群tsdb表執行major compact,刪除問題數據,最終查詢性能恢復正常。
更多思考:
如果後續還需要對這種刪除的數據進行分析,其實我們可以轉變思路,數據存儲的時候將tag變成metrics來存儲,這樣就不用擔心查詢性能問題了。
四、總結
本文從OpenTSDB的整體架構,存儲模型,存儲優化,在58的使用情況和使用過程中遇到的問題等多個方面進行了詳細描述。展望未來,我們希望OpenTSDB在數據安全,多租戶方面得到進一步的優化和完善,這樣可以將OpenTSDB打造成一個統一的平台,簡化現有的部署流程,用戶也可以更放心和更容易接入使用。