解密OpenTSDB的表存儲優化【轉】


https://yq.aliyun.com/articles/54785

摘要: 本篇文章會詳細講解OpenTSDB的表結構設計,在理解它的表結構設計的同時,分析其采取該設計的深層次原因以及優缺點。它的表結構設計完全貼合HBase的存儲模型,而表格存儲(TableStore、原OTS)與HBase有類似的存儲模型,理解透OpenTSDB的表結構設計后,我們也能夠對這類數據庫的存儲

摘要 

OpenTSDB是一個分布式的、可伸縮的時間序列數據庫,在DB-engines的時間序列數據庫排行榜上排名第五。它的特點是能夠提供最高毫秒級精度的時間序列數據存儲,能夠長久保存原始數據並且不失精度。它擁有很強的數據寫入能力,支持大並發的數據寫入,並且擁有可無限水平擴展的存儲容量。

        它的強大的數據寫入能力與存儲能力得益於它底層依賴的HBase數據庫,也得益於它在表結構設計上做的大量的存儲優化。

        本篇文章會詳細講解其表結構設計,在理解它的表結構設計的同時,分析其采取該設計的深層次原因以及優缺點。它的表結構設計完全貼合HBase的存儲模型,而表格存儲(TableStore、原OTS)與HBase有類似的存儲模型,理解透OpenTSDB的表結構設計后,我們也能夠對這類數據庫的存儲模型有一個更深的理解。

 

存儲模型

在解析OpenTSDB的表結構設計前,我們需要先對其底層的HBase的存儲模型有一個理解。

表分區

HBase會按Rowkey的范圍,將一張大表切成多個region,每個region會由一個region server加載並提供服務。Rowkey的切分與表格存儲的分區類似,一個良好設計的表,需要保證讀寫壓力能夠均勻的分散到表的各個region,這樣才能充分發揮分布式集群的能力。

 

存儲結構

05224f4c4a40c93dcddc983a7a717ff7a047de50

 
如圖所示為表結構以及對應的存儲結構示例,在HBase或表格存儲這類底層采用LSM-tree的數據庫中,表數據會按列存儲。每行中的每一列在存儲文件中都會以Key-value的形式存在於文件中。其中Key的結構為:行主鍵 + 列名,Value為列的值。該種存儲結構的特點是:
        a. 每行主鍵會重復存儲,取決於列的個數
        b. 列名會重復存儲,每一列的存儲都會攜帶列名
        c. 存儲數據按row-key排序,相鄰的row-key會存儲在相鄰的塊中

 

OpenTSDB的基本概念

OpenTSDB定義每個時間序列數據需要包含以下屬性:

1. 指標名稱(metric name)

2. 時間戳(UNIX timestamp,毫秒或者秒精度)

3. 值(64位整數或者單精度浮點數)

4. 一組標簽(tags,用於描述數據屬性,至少包含一個或多個標簽,每個標簽由tagKey和tagValue組成,tagKey和tagValue均為字符串)

 

舉個例子,在監控場景中,我們可以這樣定義一個監控指標:

 

指標名稱:
    sys.cpu.user 標簽: host = 10.101.168.111 cpu = 0 指標值: 0.5
指標名稱代表這個監控指標是對用戶態CPU的使用監控,引入了兩個標簽,分別標識該監控位於哪台機器的哪個核。

 

OpenTSDB支持的查詢場景為:指定指標名稱和時間范圍,給定一個或多個標簽名稱和標簽的值作為條件,查詢出所有的數據。

以上面那個例子舉例,我們可以查詢:

    a. sys.cpu.user (host=*,cpu=*)(1465920000 <= timestamp < 1465923600):查詢凌晨0點到1點之間,所有機器的所有CPU核上的用戶態CPU消耗。

    b. sys.cpu.user (host=10.101.168.111,cpu=*)(1465920000 <= timestamp < 1465923600):查詢凌晨0點到1點之間,某台機器的所有CPU核上的用戶態CPU消耗。

    c. sys.cpu.user (host=10.101.168.111,cpu=0)(1465920000 <= timestamp < 1465923600):查詢凌晨0點到1點之間,某台機器的第0個CPU核上的用戶態CPU消耗。

 

OpenTSDB的存儲優化

了解了OpenTSDB的基本概念后,我們來嘗試設計一下表結構。

f77d814e298bca40cdefcea04892fe702ba232c7

如上圖是一個簡單的表結構設計,rowkey采用metric name + timestamp + tags的組合,因為這幾個元素才能唯一確定一個指標值。

這張表已經能滿足我們的寫入和查詢的業務需求,但是OpenTSDB采用的表結構設計遠沒有這么簡單,我們接下來一項一項看它對表結構做的一些優化。

優化一:縮短row key

觀察這張表內存儲的數據,在rowkey的組成部分內,其實有很大一部分的重復數據,重復的指標名稱,重復的標簽。以上圖為例,如果每秒采集一次監控指標,cpu為2核,host規模為100台,則一天時間內sys.cpu.user這個監控指標就會產生17280000行數據,而這些行中,監控指標名稱均是重復的。如果能將這部分重復數據的長度盡可能的縮短,則能帶來非常大的存儲空間的節省。

 

OpenTSDB采用的策略是,為每個metric、tag key和tag value都分配一個UID,UID為固定長度三個字節。

e1e766e7defcf059535c9c184a0659b499221c38

上圖為優化后的存儲結構,可以看出,rowkey的長度大大的縮短了。rowkey的縮短,帶來了很多好處:

    a. 節省存儲空間

    b. 提高查詢效率:減少key匹配查找的時間

    c. 提高傳輸效率:不光節省了從文件系統讀取的帶寬,也節省了數據返回占用的帶寬,提高了數據寫入和讀取的速度。

    d. 緩解Java程序內存壓力:Java程序,GC是老大難的問題,能節省內存的地方盡量節省。原先用String存儲的metric name、tag key或tag value,現在均可以用3個字節的byte array替換,大大節省了內存占用。

 

優化二:減少Key-Value數

優化一是OpenTSDB做的最核心的一個優化,很直觀的可以看到存儲的數據量被大大的節省了。原理也很簡單,將長的變短。但是是否還可以進一步優化呢?

在上面的存儲模型章節中,我們了解到。HBase在底層存儲結構中,每一列都會以Key-Value的形式存儲,每一列都會包含一個rowkey。如果要進一步縮短存儲量,那就得想辦法減少Key-Value的個數。

OpenTSDB分了幾個步驟來減少Key-Value的個數:

1. 將多行合並為一行,多行單列變為單行多列。

2. 將多列合並為一列,單行多列變為單行單列。

多行單列合並為單行單列

6106c668b7104312859391a26994029372a8f9de

OpenTSDB將同屬於一個時間周期內的具有相同TSUID(相同的metric name,以及相同的tags)的數據合並為一行存儲。OpenTSDB內默認的時間周期是一個小時,也就是說同屬於這一個小時的所有數據點,會合並到一行內存儲,如圖上所示。合並為一行后,該行的rowkey中的timestamp會指定為該小時的起始時間(所屬時間周期的base時間),而每一列的列名,則記錄真實數據點的時間戳與該時間周期起始時間(base)的差值。

這里列名采用差值而不是真實值也是一個有特殊考慮的設計,如存儲模型章節所述,列名也是會存在於每個Key-Value中,占用一定的存儲空間。如果是秒精度的時間戳,需要4個字節,如果是毫秒精度的時間戳,則需要8個字節。但是如果列名只存差值且時間周期為一個小時的話,則如果是秒精度,則差值取值范圍是0-3600,只需要2個字節;如果是毫秒精度,則差值取值范圍是0-360000,只需要4個字節;所以相比存真實時間戳,這個設計是能節省不少空間的。

單行多列合並為單行單列

多行合並為單行后,並不能真實的減少Key-Value個數,因為總的列數並沒有減少。所以要達到真實的節省存儲的目的,還需要將一行的列變少,才能真正的將Key-Value數變少。

OpenTSDB采取的做法是,會在后台定期的將一行的多列合並為一列,稱之為『compaction』,合並完之后效果如下。

e85374ccb1823e8829afc5407d32ea14ae2a9078

同一行中的所有列被合並為一列,如果是秒精度的數據,則一行中的3600列會合並為1列,Key-Value數從3600個降低到只有1個。

優化三:並發寫優化

上面兩個優化主要是OpenTSDB對存儲的優化,存儲量下降以及Key-Value個數下降后,除了直觀的存儲量上的縮減,對讀和寫的效率都是有一定提升的。

時間序列數據的寫入,有一個不可規避的問題是寫熱點問題,當某一個metric下數據點很多時,則該metric很容易造成寫入熱點。OpenTSDB采取了和這篇文章中介紹的一樣的方法,允許將metric預分桶,可通過『tsd.storage.salt.buckets』配置項來配置。

7fab2b13b9c2e05508de947ca887962f211fc351
如上圖所示,預分桶后的變化就是在rowkey前會拼上一個桶編號(bucket index)。預分桶后,可將某個熱點metric的寫壓力分散到多個桶中,避免了寫熱點的產生。
 

總結

OpenTSDB作為一個應用廣泛的時間序列數據庫,在存儲上做了大量的優化,優化的選擇也是完全契合其底層依賴的HBase數據庫的存儲模型。表格存儲擁有和HBase一樣的存儲模型,這部分優化經驗可以直接借鑒使用到表格存儲的應用場景中,值得我們好好學習。有問題歡迎大家一起探討。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM