OpenTSDB 數據存儲詳解

本文首發於 vivo互聯網技術 微信公衆號
連接: https://mp.weixin.qq.com/s/qayKiwk5QAIWI7-nyD3FVA
做者:DuZhimin

隨着互聯網、尤爲是物聯網的發展,咱們須要把各類類型的終端實時監測、檢查與分析設備所採集、產生的數據記錄下來,在有時間的座標中將這些數據連點成線,往過去看能夠作成多緯度報表,揭示其趨勢性、規律性、異常性;往將來看能夠作大數據分析,機器學習,實現預測和預警。前端

這些數據的典型特色是:產生頻率快(每個監測點一秒鐘內可產生多條數據)、嚴重依賴於採集時間(每一條數據均要求對應惟一的時間)、測點多信息量大(實時監測系統均有成千上萬的監測點,監測點每秒鐘都產生數據,天天產生幾十GB的數據量)。數據庫

基於時間序列數據的特色,關係型數據庫沒法知足對時間序列數據的有效存儲與處理,所以迫切須要一種專門針對時間序列數據來作優化處理的數據庫系統。微信

1、簡介

一、時序數據

時序數據是基於時間的一系列的數據。架構

二、時序數據庫

時序數據庫就是存放時序數據的數據庫,而且須要支持時序數據的快速寫入、持久化、多緯度的聚合查詢等基本功能。機器學習

對比傳統數據庫僅僅記錄了數據的當前值,時序數據庫則記錄了全部的歷史數據。同時時序數據的查詢也老是會帶上時間做爲過濾條件。分佈式

三、OpenTSDB

毫無遺漏的接收並存儲大量的時間序列數據。工具

3.一、存儲

  1. 無需轉換,寫的是什麼數據存的就是什麼數據
  2. 時序數據以毫秒的精度保存
  3. 永久保留原始數據

3.二、擴展性

  1. 運行在Hadoop 和 HBase之上
  2. 可擴展到每秒數百萬次寫入
  3. 能夠經過添加節點擴容

3.三、讀能力

  1. 直接經過內置的GUI來生成圖表
  2. 還能夠經過HTTP API查詢數據
  3. 另外還可使用開源的前端與其交互

四、OpenTSDB核心概念

咱們來看一下這樣一段信息:2019-12-5 22:31:21版本號爲‘3.2.1’的某產品客戶端的首頁PV是1000Woop

  1. Metric:指標,即平時咱們所說的監控項。譬如上面的PV
  2. Tags:維度,也即標籤,在OpenTSDB裏面,Tags由tagk和tagv組成的鍵值對,即tagk=takv。標籤是用來描述Metric的,好比上面的某產品客戶端的版本號 version=‘3.2.1’
  3. Value:一個Value表示一個metric的實際數值,好比:1000W
  4. Timestamp:即時間戳,用來描述Value是何時發生的:好比:2019-12-5 22:31:21
  5. Data Point:即某個Metric在某個時間點的數值,Data Point包括如下部分:Metric、Tags、Value、Timestamp
  6. 保存到OpenTSDB的數據就是無數個DataPoint

上面描述2019-12-5 22:31:21版本號爲‘3.2.1’的某產品客戶端的首頁PV是1000W,就是1個DataPoint。性能

2、OpenTSDB的部署架構

一、架構圖

二、說明

  1. OpenTSDB底層是使用HBase來存儲數據的,也就是說搭建OpenTSDB以前,必須先搭建好HBase環境。
  2. OpenTSDB是由一系列的TSD和實用的命令行工具組成。
  3. 應用經過運行一個或多個tsd(Time Series Daemon, OpenTSDB的節點)來與OpenTSDB的交互。
  4. 每一個TSD是獨立的,沒有master,沒有共享狀態,因此你能夠運行儘量多的 TSD 來處理工做負載。

3、HBase簡介

從OpenTSDB的部署架構中咱們看到OpenTSDB是創建在HBase之上的,那麼HBase又是啥呢?爲了更好的剖析OpenTSDB,這裏咱們簡要介紹一下HBase。學習

一、HBase是一個高可靠性、強一致性、高性能、面向列、可伸縮、實時讀寫的分佈式開源NoSQL數據庫。

二、HBase是無模式數據庫,只須要提早定義列簇,並不須要指定列限定符。同時它也是無類型數據庫,全部數據都是按二進制字節方式存儲的。

三、它把數據存儲在表中,表按「行鍵,列簇,列限定符和時間版本」的四維座標系來組織,也就是說若是要惟必定位一個值,須要四個都惟一才行。下面參考Excel來講明一下:

四、對 HBase 的操做和訪問有 5 個基本方式,即 Get、Put、Delete 和 Scan 以及 Increment,HBase 基於非行鍵值查詢的惟一途徑是經過帶過濾器的掃描。

五、數據在HBase中的存儲(物理上):

六、數據在HBase中的存儲(邏輯上):

4、 支撐OpenTSDB運行的HBase表

若是你第一次用你的HBase實例運行OpenTSDB,須要建立必要的HBase表,OpenTSDB 運行僅僅須要四張表:tsdb, tsdb-uid, tsdb-tree 和 tsdb-meta,全部的DataPoint 數據都保存在這四張表中,建表語句以下:

一、tsdb-uid

create 'tsdb-uid',
{NAME => 'id', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'},
{NAME => 'name', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}

二、tsdb

create 'tsdb',
{NAME => 't', VERSIONS => 1, COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}

三、tsdb-tree

create 'tsdb-tree',
{NAME => 't', VERSIONS => 1, COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}

四、tsdb-meta

create 'tsdb-meta',
{NAME => 'name', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'}

後面將對照實際數據來專門講解這四張表分別存儲的內容。

5、 OpenTSDB是如何把一個數據點保存到HBase中的呢?

一、首先檢查一下四個表裏面的數據

從上面看,四個表裏面的數據都是空的

二、而後咱們往OpenTSDB寫一個數據點

@Test
public void addData() {
    String metricName = "metric";
    long value = 1;
    Map<String, String> tags = new HashMap<String, String>();
    tags.put("tagk", "tagv");
    long timestamp = System.currentTimeMillis();
    tsdb.addPoint(metricName, timestamp, value, tags);
    System.out.println("------------");
}

三、插入數據以後咱們再來查看一下四個表數據

發現HBase裏面有數據,在tsdb-uid、tsdb、和 tsdb-meta 表裏面有數據,而tsdb-tree 表裏面沒任何數據,下面咱們針對這些數據作一下具體分析。

四、tsdb-tree表

它是一張索引表,用於展現樹狀結構的,相似於文件系統,以方便其餘系統使用,這裏咱們不作深刻的分析。

經過配置項tsd.core.tree.enable_processing來打開是否須要往此表裏面寫入數據。

五、tsdb-meta表

這個表是OpenTSDB中不一樣時間序列的一個索引,能夠用來存儲一些額外的信息,該表只有一個列族name,兩個列,分別爲ts_meta、ts_ctr。這個表裏面的數據是能夠根據配置項配置來控制是否生成與否,生成幾個列,具體的配置項有:

tsd.core.meta.enable_realtime_ts
tsd.core.meta.enable_tsuid_incrementing
tsd.core.meta.enable_tsuid_tracking

Row Key 和tsdb表同樣,其中不包含時間戳,<metric_uid><tagk1><tagv1>[...<tagkN><tagvN>]

ts_meta Column 和UIDMeta類似,其爲UTF-8編碼的JSON格式字符串

ts_ctr Column 計數器,用來記錄一個時間序列中存儲的數據個數,其列名爲ts_ctr,爲8位有符號的整數。

六、tsdb-uid表數據分析

tsdb-uid用來存儲UID映射,包括正向的和反向的。存在兩列族,一列族叫作name用來將一個UID映射到一個字符串,另外一個列族叫作id,用來將字符串映射到UID。列族的每一行都至少有如下三列中的一個:

  • metrics 將metric的名稱映射到UID
  • tagk 將tag名稱映射到UID
  • tagv 將tag的值映射到UID

若是配置了metadata,則name列族還能夠包括額外的metatata列。

6.一、id 列族

  • Row Key:實際的指標名稱或者tagK或者tagV
  • Column Qualifiers:metrics、tagk、tagv三種列類型中一種
  • Column Value :一個無符號的整數,默認是被編碼爲3個byte,自增的數字,其值爲UID

6.二、name 列族

  • Row Key :UID,就是ID列簇的值
  • Column Qualifiers:metrics、tagk、tagv、metrics_meta、tagk_meta、tagv_meta六種列類型中一種,*_meta是須要開啓tsd.core.meta.enable_realtime_uid纔會生成
  • Column Value:與UID對應的字符串,對於一個*_meta列,其值將會是一個UTF-8編碼的JSON格式字符串。不要在OpenTSDB外部去修改該值,其中的字段順序會影響CAS調用。

七、tsdb表:

時間點數據就保存在此表中,只有一個列簇t:

7.一、RowKey格式

  • UID:默認編碼爲3 Bytes,而時間戳會編碼爲4 Bytes
  • salt:打散同一metric不一樣時間線的熱點
  • metric, tagK, tagV:實際存儲的是字符串對應的UID(在tsdb-uid表中)
  • timestamp:每小時數據存在一行,記錄的是每小時整點秒級時間戳

7.二、Column格式

column qualifier 佔用2 Bytes或者4 Bytes,

佔用2 Bytes時表示以秒爲單位的偏移,格式爲:

  • 12 bits:相對row表示的小時的delta, 最多2^ 12 = 4096 > 3600所以沒有問題
  • 1 bit: an integer or floating point
  • 3 bits: 標明數據的長度,其長度必須是一、二、四、8。000表示1個byte,010表示2byte,011表示4byte,100表示8byte

佔用4 Bytes時表示以毫秒爲單位的偏移,格式爲:

  • 4 bits:十六進制的1或者F
  • 22 bits:毫秒偏移
  • 2 bit:保留
  • 1 bit: an integer or floating point,0表示整數,1表示浮點數
  • 3 bits: 標明數據的長度,其長度必須是一、二、四、8。000表示1個byte,010表示2byte,011表示4byte,100表示8byte

7.三、value

value 使用8 Bytes存儲,既能夠存儲long,也能夠存儲double。

7.四、tsdb表設計的特色:

  1. metric和tag映射成UID,不存儲實際字符串,以節約空間。
  2. 每條時間線每小時的數據點歸在一行,每列是一個數據點,這樣每列只須要記錄與這行起始時間偏移,以節省空間。
  3. 每列就是一個KeyValue。

6、 寫在最後

一、應用場景

  • 做爲時序數據庫,OpenTSDB 不只僅能夠提供原始數據的查詢,而且還支持對原始數據的聚合能力,支持過濾、過濾以後的聚合計算。
  • 支持降採樣查詢,好比原始數據是1分鐘一個數據點,若是我想1個小時一個數據點進行展現,也能支持。
  • 支持根據維度分組查詢,好比我有一箇中國地市的數據,如今我想根據省份進行分組以後查詢,也能支持。

二、使用注意事項

  • OpenTSDB 默認狀況下的字符集是ISO-8859-1,爲何會使用這個字符集呢,是由於它的編碼是單字節編碼,編碼後的長度是固定的,若是要支持中文,須要對源碼進行編譯,修改成UTF-8便可。
  • 默認提供的HBase建表語句是沒有預分區的,這樣會致使大批量數據寫入的時候有熱點問題,建議進行預分區。
  • OpenTSDB不適合超大數據量,在千萬級、億級中提取幾萬條數據,好比某個指標半年內的5分鐘級別的數據,仍是很快響應的。但若是再提取多點數據,幾十萬,百萬這樣的量級,又或者提取後再作個聚合運算,OpenTSDB 就勉爲其難,實際使用的時候用做服務端機器的監控無任何問題,若是做爲客戶端APP監控,響應就比較遲緩。
  • OpenTSDB 只有4 張HBase 表,全部的數據都存放在一張表,這就意味在OpenTSDB 這個層級上是沒法更小的粒度來區別對待不一樣業務,好比不一樣的業務建不一樣的表存儲數據。
  • OpenTSDB 支持實時聚合計算功能,可是基於單點,因此運算能力有限。

三、展望

若是須要支持特大批量時序數據,建議使用Druid或InfluxDB,其中InfluxDB是最易用的時序數據庫。

更多內容敬請關注vivo 互聯網技術微信公衆號

注:轉載文章請先與微信號:Labs2020聯繫。

相關文章
相關標籤/搜索