OpenTSDB 資料儲存詳解

vivo網際網路技術發表於2020-07-16

本文首發於 vivo網際網路技術 微信公眾號
連結: https://mp.weixin.qq.com/s/qayKiwk5QAIWI7-nyD3FVA
作者:DuZhimin

隨著網際網路、尤其是物聯網的發展,我們需要把各種型別的終端實時監測、檢查與分析裝置所採集、產生的資料記錄下來,在有時間的座標中將這些資料連點成線,往過去看可以做成多緯度報表,揭示其趨勢性、規律性、異常性;往未來看可以做大資料分析,機器學習,實現預測和預警。

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

基於時間序列資料的特點,關係型資料庫無法滿足對時間序列資料的有效儲存與處理,因此迫切需要一種專門針對時間序列資料來做最佳化處理的資料庫系統。

一、簡介

1、時序資料

時序資料是基於時間的一系列的資料。

2、時序資料庫

時序資料庫就是存放時序資料的資料庫,並且需要支援時序資料的快速寫入、持久化、多緯度的聚合查詢等基本功能。

對比傳統資料庫僅僅記錄了資料的當前值,時序資料庫則記錄了所有的歷史資料。同時時序資料的查詢也總是會帶上時間作為過濾條件。

3、OpenTSDB

毫無遺漏的接收並儲存大量的時間序列資料。

3.1、儲存

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

3.2、擴充套件性

  1. 執行在Hadoop 和 HBase之上
  2. 可擴充套件到每秒數百萬次寫入
  3. 可以透過新增節點擴容

3.3、讀能力

  1. 直接透過內建的GUI來生成圖表
  2. 還可以透過HTTP API查詢資料
  3. 另外還可以使用開源的前端與其互動

4、OpenTSDB核心概念

我們來看一下這樣一段資訊:2019-12-5 22:31:21版本號為‘3.2.1’的某產品客戶端的首頁PV是1000W

  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。

二、OpenTSDB的部署架構

1、架構圖

2、說明

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

三、HBase簡介

從OpenTSDB的部署架構中我們看到OpenTSDB是建立在HBase之上的,那麼HBase又是啥呢?為了更好的剖析OpenTSDB,這裡我們簡要介紹一下HBase。

1、HBase是一個高可靠性、強一致性、高效能、面向列、可伸縮、實時讀寫的分散式開源NoSQL資料庫。

2、HBase是無模式資料庫,只需要提前定義列簇,並不需要指定列限定符。同時它也是無型別資料庫,所有資料都是按二進位制位元組方式儲存的。

3、它把資料儲存在表中,表按“行鍵,列簇,列限定符和時間版本”的四維座標系來組織,也就是說如果要唯一定位一個值,需要四個都唯一才行。下面參考Excel來說明一下:

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

5、資料在HBase中的儲存(物理上):

6、資料在HBase中的儲存(邏輯上):

四、 支撐OpenTSDB執行的HBase表

如果你第一次用你的HBase例項執行OpenTSDB,需要建立必要的HBase表,OpenTSDB 執行僅僅需要四張表:tsdb, tsdb-uid, tsdb-tree 和 tsdb-meta,所有的DataPoint 資料都儲存在這四張表中,建表語句如下:

1、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'}

2、tsdb

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

3、tsdb-tree

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

4、tsdb-meta

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

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

五、 OpenTSDB是如何把一個資料點儲存到HBase中的呢?

1、首先檢查一下四個表裡面的資料

從上面看,四個表裡面的資料都是空的

2、然後我們往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("------------");
}

3、插入資料之後我們再來檢視一下四個表資料

發現HBase裡面有資料,在tsdb-uid、tsdb、和 tsdb-meta 表裡面有資料,而tsdb-tree 表裡面沒任何資料,下面我們針對這些資料做一下具體分析。

4、tsdb-tree表

它是一張索引表,用於展示樹狀結構的,類似於檔案系統,以方便其他系統使用,這裡我們不做深入的分析。

透過配置項tsd.core.tree.enable_processing來開啟是否需要往此表裡面寫入資料。

5、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位有符號的整數。

6、tsdb-uid表資料分析

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

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

如果配置了metadata,則name列族還可以包括額外的metatata列。

6.1、id 列族

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

6.2、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呼叫。

7、tsdb表:

時間點資料就儲存在此表中,只有一個列簇t:

OpenTSDB 資料儲存詳解

7.1、RowKey格式

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

7.2、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: 標明資料的長度,其長度必須是1、2、4、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: 標明資料的長度,其長度必須是1、2、4、8。000表示1個byte,010表示2byte,011表示4byte,100表示8byte

7.3、value

value 使用8 Bytes儲存,既可以儲存long,也可以儲存double。

7.4、tsdb表設計的特點:

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

六、 寫在最後

1、應用場景

  • 作為時序資料庫,OpenTSDB 不僅僅可以提供原始資料的查詢,並且還支援對原始資料的聚合能力,支援過濾、過濾之後的聚合計算。

  • 支援降取樣查詢,比如原始資料是1分鐘一個資料點,如果我想1個小時一個資料點進行展示,也能支援。

  • 支援根據維度分組查詢,比如我有一箇中國地市的資料,現在我想根據省份進行分組之後查詢,也能支援。

2、使用注意事項

  • OpenTSDB 預設情況下的字符集是ISO-8859-1,為什麼會使用這個字符集呢,是因為它的編碼是單位元組編碼,編碼後的長度是固定的,如果要支援中文,需要對原始碼進行編譯,修改為UTF-8即可。

  • 預設提供的HBase建表語句是沒有預分割槽的,這樣會導致大批次資料寫入的時候有熱點問題,建議進行預分割槽。

  • OpenTSDB不適合超大資料量,在千萬級、億級中提取幾萬條資料,比如某個指標半年內的5分鐘級別的資料,還是很快響應的。但如果再提取多點資料,幾十萬,百萬這樣的量級,又或者提取後再做個聚合運算,OpenTSDB 就勉為其難,實際使用的時候用作服務端機器的監控無任何問題,如果作為客戶端APP監控,響應就比較遲緩。

  • OpenTSDB 只有4 張HBase 表,所有的資料都存放在一張表,這就意味在OpenTSDB 這個層級上是無法更小的粒度來區別對待不同業務,比如不同的業務建不同的表儲存資料。

  • OpenTSDB 支援實時聚合計算功能,但是基於單點,所以運算能力有限。

3、展望

如果需要支援特大批次時序資料,建議使用Druid或InfluxDB,其中InfluxDB是最易用的時序資料庫。

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

相關文章