隨著互聯(lián)網(wǎng)、尤其是物聯(lián)網(wǎng)的發(fā)展,我們需要把各種類型的終端實時監(jiān)測、檢查與分析設(shè)備所采集、產(chǎn)生的數(shù)據(jù)記錄下來,在有時間的坐標中將這些數(shù)據(jù)連點成線,往過去看可以做成多緯度報表,揭示其趨勢性、規(guī)律性、異常性;往未來看可以做大數(shù)據(jù)分析,機器學(xué)習(xí),實現(xiàn)預(yù)測和預(yù)警。
這些數(shù)據(jù)的典型特點是:產(chǎn)生頻率快(每一個監(jiān)測點一秒鐘內(nèi)可產(chǎn)生多條數(shù)據(jù))、嚴重依賴于采集時間(每一條數(shù)據(jù)均要求對應(yīng)唯一的時間)、測點多信息量大(實時監(jiān)測系統(tǒng)均有成千上萬的監(jiān)測點,監(jiān)測點每秒鐘都產(chǎn)生數(shù)據(jù),每天產(chǎn)生幾十GB的數(shù)據(jù)量)。
基于時間序列數(shù)據(jù)的特點,關(guān)系型數(shù)據(jù)庫無法滿足對時間序列數(shù)據(jù)的有效存儲與處理,因此迫切需要一種專門針對時間序列數(shù)據(jù)來做優(yōu)化處理的數(shù)據(jù)庫系統(tǒng)。
一、簡介
1、時序數(shù)據(jù)
時序數(shù)據(jù)是基于時間的一系列的數(shù)據(jù)。
2、時序數(shù)據(jù)庫
時序數(shù)據(jù)庫就是存放時序數(shù)據(jù)的數(shù)據(jù)庫,并且需要支持時序數(shù)據(jù)的快速寫入、持久化、多緯度的聚合查詢等基本功能。
對比傳統(tǒng)數(shù)據(jù)庫僅僅記錄了數(shù)據(jù)的當前值,時序數(shù)據(jù)庫則記錄了所有的歷史數(shù)據(jù)。同時時序數(shù)據(jù)的查詢也總是會帶上時間作為過濾條件。
3、OpenTSDB
毫無遺漏的接收并存儲大量的時間序列數(shù)據(jù)。
3.1、存儲
無需轉(zhuǎn)換,寫的是什么數(shù)據(jù)存的就是什么數(shù)據(jù)
時序數(shù)據(jù)以毫秒的精度保存
永久保留原始數(shù)據(jù)
3.2、擴展性
運行在Hadoop 和 HBase之上
可擴展到每秒數(shù)百萬次寫入
可以通過添加節(jié)點擴容
3.3、讀能力
直接通過內(nèi)置的GUI來生成圖表
還可以通過HTTP API查詢數(shù)據(jù)
另外還可以使用開源的前端與其交互
4、OpenTSDB核心概念
我們來看一下這樣一段信息:2019-12-5 22:31:21版本號為‘3.2.1’的某產(chǎn)品客戶端的首頁PV是1000W
Metric:指標,即平時我們所說的監(jiān)控項。譬如上面的PV
Tags:維度,也即標簽,在OpenTSDB里面,Tags由tagk和tagv組成的鍵值對,即tagk=takv。標簽是用來描述Metric的,比如上面的某產(chǎn)品客戶端的版本號 version=‘3.2.1’
Value:一個Value表示一個metric的實際數(shù)值,比如:1000W
Timestamp:即時間戳,用來描述Value是什么時候發(fā)生的:比如:2019-12-5 22:31:21
Data Point:即某個Metric在某個時間點的數(shù)值,Data Point包括以下部分:Metric、Tags、Value、Timestamp
保存到OpenTSDB的數(shù)據(jù)就是無數(shù)個DataPoint
上面描述2019-12-5 22:31:21版本號為‘3.2.1’的某產(chǎn)品客戶端的首頁PV是1000W,就是1個DataPoint。
二、OpenTSDB的部署架構(gòu)
1、架構(gòu)圖
2、說明
OpenTSDB底層是使用HBase來存儲數(shù)據(jù)的,也就是說搭建OpenTSDB之前,必須先搭建好HBase環(huán)境。
OpenTSDB是由一系列的TSD和實用的命令行工具組成。
應(yīng)用通過運行一個或多個tsd(Time Series Daemon, OpenTSDB的節(jié)點)來與OpenTSDB的交互。
每個TSD是獨立的,沒有master,沒有共享狀態(tài),所以你可以運行盡可能多的 TSD 來處理工作負載。
三、HBase簡介
從OpenTSDB的部署架構(gòu)中我們看到OpenTSDB是建立在HBase之上的,那么HBase又是啥呢?為了更好的剖析OpenTSDB,這里我們簡要介紹一下HBase。
1、HBase是一個高可靠性、強一致性、高性能、面向列、可伸縮、實時讀寫的分布式開源NoSQL數(shù)據(jù)庫。
2、HBase是無模式數(shù)據(jù)庫,只需要提前定義列簇,并不需要指定列限定符。同時它也是無類型數(shù)據(jù)庫,所有數(shù)據(jù)都是按二進制字節(jié)方式存儲的。
3、它把數(shù)據(jù)存儲在表中,表按“行鍵,列簇,列限定符和時間版本”的四維坐標系來組織,也就是說如果要唯一定位一個值,需要四個都唯一才行。下面參考Excel來說明一下:
4、對 HBase 的操作和訪問有 5 個基本方式,即 Get、Put、Delete 和 Scan 以及 Increment,HBase 基于非行鍵值查詢的唯一途徑是通過帶過濾器的掃描。
5、數(shù)據(jù)在HBase中的存儲(物理上):
6、數(shù)據(jù)在HBase中的存儲(邏輯上):
四、 支撐OpenTSDB運行的HBase表
如果你第一次用你的HBase實例運行OpenTSDB,需要創(chuàng)建必要的HBase表,OpenTSDB 運行僅僅需要四張表:tsdb, tsdb-uid, tsdb-tree 和 tsdb-meta,所有的DataPoint 數(shù)據(jù)都保存在這四張表中,建表語句如下:
1、tsdb-uid
1 2 3 |
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
1 2 |
create 'tsdb', {NAME => 't', VERSIONS => 1, COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'} |
3、tsdb-tree
1 2 |
create 'tsdb-tree', {NAME => 't', VERSIONS => 1, COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'} |
4、tsdb-meta
1 2 |
create 'tsdb-meta', {NAME => 'name', COMPRESSION => 'NONE', BLOOMFILTER => 'ROW', DATA_BLOCK_ENCODING => 'PREFIX_TREE'} |
后面將對照實際數(shù)據(jù)來專門講解這四張表分別存儲的內(nèi)容。
五、 OpenTSDB是如何把一個數(shù)據(jù)點保存到HBase中的呢?
1、首先檢查一下四個表里面的數(shù)據(jù)
從上面看,四個表里面的數(shù)據(jù)都是空的
2、然后我們往OpenTSDB寫一個數(shù)據(jù)點
1 2 3 4 5 6 7 8 9 10 |
@Test public void addData() { ????String metricName = "metric"; ????long value = 1; ????Map tags = new HashMap(); ????tags.put("tagk", "tagv"); ????long timestamp = System.currentTimeMillis(); ????tsdb.addPoint(metricName, timestamp, value, tags); ????System.out.println("------------"); } |
3、插入數(shù)據(jù)之后我們再來查看一下四個表數(shù)據(jù)
發(fā)現(xiàn)HBase里面有數(shù)據(jù),在tsdb-uid、tsdb、和 tsdb-meta 表里面有數(shù)據(jù),而tsdb-tree 表里面沒任何數(shù)據(jù),下面我們針對這些數(shù)據(jù)做一下具體分析。
4、tsdb-tree表
它是一張索引表,用于展示樹狀結(jié)構(gòu)的,類似于文件系統(tǒng),以方便其他系統(tǒng)使用,這里我們不做深入的分析。
通過配置項tsd.core.tree.enable_processing來打開是否需要往此表里面寫入數(shù)據(jù)。
5、tsdb-meta表
這個表是OpenTSDB中不同時間序列的一個索引,可以用來存儲一些額外的信息,該表只有一個列族name,兩個列,分別為ts_meta、ts_ctr。這個表里面的數(shù)據(jù)是可以根據(jù)配置項配置來控制是否生成與否,生成幾個列,具體的配置項有:
1 2 3 |
tsd.core.meta.enable_realtime_ts tsd.core.meta.enable_tsuid_incrementing tsd.core.meta.enable_tsuid_tracking |
Row Key?和tsdb表一樣,其中不包含時間戳,[...]
ts_meta?Column?和UIDMeta相似,其為UTF-8編碼的JSON格式字符串
ts_ctr Column 計數(shù)器,用來記錄一個時間序列中存儲的數(shù)據(jù)個數(shù),其列名為ts_ctr,為8位有符號的整數(shù)。
6、tsdb-uid表數(shù)據(jù)分析
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 :?一個無符號的整數(shù),默認是被編碼為3個byte,自增的數(shù)字,其值為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對應(yīng)的字符串,對于一個*_meta列,其值將會是一個UTF-8編碼的JSON格式字符串。不要在OpenTSDB外部去修改該值,其中的字段順序會影響CAS調(diào)用。
7、tsdb表:
時間點數(shù)據(jù)就保存在此表中,只有一個列簇t:
7.1、RowKey格式
UID:默認編碼為3 Bytes,而時間戳?xí)幋a為4 Bytes
salt:打散同一metric不同時間線的熱點
metric, tagK, tagV:實際存儲的是字符串對應(yīng)的UID(在tsdb-uid表中)
timestamp:每小時數(shù)據(jù)存在一行,記錄的是每小時整點秒級時間戳
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: 標明數(shù)據(jù)的長度,其長度必須是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表示整數(shù),1表示浮點數(shù)
3 bits: 標明數(shù)據(jù)的長度,其長度必須是1、2、4、8。000表示1個byte,010表示2byte,011表示4byte,100表示8byte
7.3、value
value 使用8 Bytes存儲,既可以存儲long,也可以存儲double。
7.4、tsdb表設(shè)計的特點:
metric和tag映射成UID,不存儲實際字符串,以節(jié)約空間。
每條時間線每小時的數(shù)據(jù)點歸在一行,每列是一個數(shù)據(jù)點,這樣每列只需要記錄與這行起始時間偏移,以節(jié)省空間。
每列就是一個KeyValue。
六、 寫在最后
1、應(yīng)用場景
作為時序數(shù)據(jù)庫,OpenTSDB 不僅僅可以提供原始數(shù)據(jù)的查詢,并且還支持對原始數(shù)據(jù)的聚合能力,支持過濾、過濾之后的聚合計算。
支持降采樣查詢,比如原始數(shù)據(jù)是1分鐘一個數(shù)據(jù)點,如果我想1個小時一個數(shù)據(jù)點進行展示,也能支持。
支持根據(jù)維度分組查詢,比如我有一個中國地市的數(shù)據(jù),現(xiàn)在我想根據(jù)省份進行分組之后查詢,也能支持。
2、使用注意事項
OpenTSDB 默認情況下的字符集是ISO-8859-1,為什么會使用這個字符集呢,是因為它的編碼是單字節(jié)編碼,編碼后的長度是固定的,如果要支持中文,需要對源碼進行編譯,修改為UTF-8即可。
默認提供的HBase建表語句是沒有預(yù)分區(qū)的,這樣會導(dǎo)致大批量數(shù)據(jù)寫入的時候有熱點問題,建議進行預(yù)分區(qū)。
OpenTSDB不適合超大數(shù)據(jù)量,在千萬級、億級中提取幾萬條數(shù)據(jù),比如某個指標半年內(nèi)的5分鐘級別的數(shù)據(jù),還是很快響應(yīng)的。但如果再提取多點數(shù)據(jù),幾十萬,百萬這樣的量級,又或者提取后再做個聚合運算,OpenTSDB 就勉為其難,實際使用的時候用作服務(wù)端機器的監(jiān)控?zé)o任何問題,如果作為客戶端APP監(jiān)控,響應(yīng)就比較遲緩。
OpenTSDB 只有4 張HBase 表,所有的數(shù)據(jù)都存放在一張表,這就意味在OpenTSDB 這個層級上是無法更小的粒度來區(qū)別對待不同業(yè)務(wù),比如不同的業(yè)務(wù)建不同的表存儲數(shù)據(jù)。
OpenTSDB 支持實時聚合計算功能,但是基于單點,所以運算能力有限。
3、展望
如果需要支持特大批量時序數(shù)據(jù),建議使用Druid或InfluxDB,其中InfluxDB是最易用的時序數(shù)據(jù)庫。
編輯:hfy
評論
查看更多