TSDB時序數據庫簡單說明

1.基礎


1.1 時序數據的定義


什麼是時間序列數據(Time Series Data,TSD,以下簡稱時序)從定義上來說,就是一串按時間維度索引的數據。用描述性的語言來解釋什麼是時序數據,簡單的說,就是這類數據描述了某個被測量的主體在一個時間範圍內的每個時間點上的測量值。它普遍存在於IT基礎設施、運維監控系統和物聯網中。
  
對時序數據進行建模的話,會包含三個重要部分,分別是:主體,時間點和測量值。套用這套模型,你會發現你在日常工作生活中,無時無刻不在接觸着這類數據。

如果你是一個股民,某隻股票的股價就是一類時序數據,其記錄着每個時間點該股票的股價。
如果你是一個運維人員,監控數據是一類時序數據,例如對於機器的CPU的監控數據,就是記錄着每個時間點機器上CPU的實際消耗值。
時序數據從時間維度上將孤立的觀測值連成一條線,從而揭示軟硬件系統的狀態變化。孤立的觀測值不能叫時序數據,但如果把大量的觀測值用時間線串起來,我們就可以研究和分析觀測值的趨勢及規律。

1.2 時序數據的特點


1.2.1 時序數據的數學模型


上面介紹了時序數據的基本概念,也說明了分析時序數據的意義。那麼時序數據該怎樣存儲呢?數據的存儲要考慮其數學模型和特點,時序數據當然也不例外。所以這裏先介紹時序數據的數學模型和特點。

下圖爲一段時序數據,記錄了一段時間內的某個集羣裏各機器上各端口的出入流量,每半小時記錄一個觀測值。這裏以圖中的數據爲例,介紹下時序數據的數學模型(不同的時序數據庫中,基本概念的稱謂有可能不同,這裏以騰訊CTSDB爲準):

measurement: 度量的數據集,類似於關係型數據庫中的 table;

point: 一個數據點,類似於關係型數據庫中的 row;

timestamp: 時間戳,表徵採集到數據的時間點;

tag: 維度列,代表數據的歸屬、屬性,表明是哪個設備/模塊產生的,一般不隨着時間變化,供查詢使用;

field: 指標列,代表數據的測量值,隨時間平滑波動,不需要查詢。

 

 

如上圖所示,這組數據的measurement爲Network,每個point由以下部分組成:

timestamp:時間戳

兩個tag:host、port,代表每個point歸屬於哪臺機器的哪個端口

兩個field:bytes_in、bytes_out,代表piont的測量值,半小時內出入流量的平均值
同一個host、同一個port,每半小時產生一個point,隨着時間的增長,field(bytes_in、bytes_out)不斷變化。如host:host4,port:51514,timestamp從02:00 到02:30的時間段內,bytes_in 從 37.937上漲到38.089,bytes_out從2897.26上漲到3009.86,說明這一段時間內該端口服務壓力升高。

1.2.2 時序數據特點


數據模式: 時序數據隨時間增長,相同維度重複取值,指標平滑變化:這點從上面的Network表的數據變化可以看出。
寫入: 持續高併發寫入,無更新操作:時序數據庫面對的往往是百萬甚至千萬數量級終端設備的實時數據寫入(如摩拜單車2017年全國車輛數爲千萬級),但數據大多表徵設備狀態,寫入後不會更新。
查詢: 按不同維度對指標進行統計分析,且存在明顯的冷熱數據,一般只會頻繁查詢近期數據。


1.3 時序數據的存儲


1.3.1 傳統關係型數據庫存儲時序數據的問題


有了時序數據後,該存儲在哪裏呢?首先我們看下傳統的關係型數據庫解決方案在存儲時序數據時會遇到什麼問題。

很多人可能認爲在傳統關係型數據庫上加上時間戳一列就能作爲時序數據庫。數據量少的時候確實也沒問題。但時序數據往往是由百萬級甚至千萬級終端設備產生的,寫入併發量比較高,屬於海量數據場景。

MySQL在海量的時序數據場景下存在如下問題:

存儲成本大:對於時序數據壓縮不佳,需佔用大量機器資源;
維護成本高:單機系統,需要在上層人工的分庫分表,維護成本高;
寫入吞吐低:單機寫入吞吐低,很難滿足時序數據千萬級的寫入壓力;
查詢性能差:適用於交易處理,海量數據的聚合分析性能差。
另外,使用Hadoop生態(Hadoop、Spark等)存儲時序數據會有以下問題:

數據延遲高:離線批處理系統,數據從產生到可分析,耗時數小時、甚至天級;
查詢性能差:不能很好的利用索引,依賴MapReduce任務,查詢耗時一般在分鐘級。
可以看到時序數據庫需要解決以下幾個問題:

時序數據的寫入:如何支持每秒鐘上千萬上億數據點的寫入。
時序數據的讀取:如何支持在秒級對上億數據的分組聚合運算。
成本敏感:由海量數據存儲帶來的是成本問題。如何更低成本的存儲這些數據,將成爲時序數據庫需要解決的重中之重。


1.3.2 時序數據庫


***時序數據庫產品的發明都是爲了解決傳統關係型數據庫在時序數據存儲和分析上的不足和缺陷,這類產品被統一歸類爲時序數據庫。***針對時序數據的特點對寫入、存儲、查詢等流程進行了優化,這些優化與時序數據的特點息息相關:

存儲成本:
利用時間遞增、維度重複、指標平滑變化的特性,合理選擇編碼壓縮算法,提高數據壓縮比;
通過預降精度,對歷史數據做聚合,節省存儲空間。

高併發寫入:
批量寫入數據,降低網絡開銷;
數據先寫入內存,再週期性的dump爲不可變的文件存儲。

低查詢延時,高查詢併發:
優化常見的查詢模式,通過索引等技術降低查詢延時;
通過緩存、routing等技術提高查詢併發。

1.3.3 時序數據的存儲原理


傳統數據庫存儲採用的都是 B tree,這是由於其在查詢和順序插入時有利於減少尋道次數的組織形式。我們知道磁盤尋道時間是非常慢的,一般在 10ms 左右。磁盤的隨機讀寫慢就慢在尋道上面。對於隨機寫入 B tree 會消耗大量的時間在磁盤尋道上,導致速度很慢。我們知道 SSD 具有更快的尋道時間,但並沒有從根本上解決這個問題。

對於 90% 以上場景都是寫入的時序數據庫,B tree 很明顯是不合適的。

業界主流都是採用 LSM tree 替換 B tree,比如 Hbase, Cassandra 等 nosql 。這裏我們詳細介紹一下。

LSM tree 包括內存裏的數據結構和磁盤上的文件兩部分。分別對應 Hbase 裏的 MemStore 和 HLog;對應 Cassandra 裏的 MemTable 和 sstable。

LSM tree 操作流程如下:

 

數據寫入和更新時首先寫入位於內存裏的數據結構。爲了避免數據丟失也會先寫到 WAL 文件中。
內存裏的數據結構會定時或者達到固定大小會刷到磁盤。這些磁盤上的文件不會被修改。
隨着磁盤上積累的文件越來越多,會定時的進行合併操作,消除冗餘數據,減少文件數量。

可以看到 LSM tree 核心思想就是通過內存寫和後續磁盤的順序寫入獲得更高的寫入性能,避免了隨機寫入。但同時也犧牲了讀取性能,因爲同一個 key 的值可能存在於多個 HFile 中。爲了獲取更好的讀取性能,可以通過 bloom filter 和 compaction 得到,這裏限於篇幅就不詳細展開。

 

1.3.4 分佈式存儲


時序數據庫面向的是海量數據的寫入存儲讀取,單機是無法解決問題的。所以需要採用多機存儲,也就是分佈式存儲。

分佈式存儲首先要考慮的是如何將數據分佈到多臺機器上面,也就是分片(sharding)問題。下面我們就時序數據庫分片問題展開介紹。分片問題由分片方法的選擇和分片的設計組成。

分片方法


時序數據庫的分片方法和其他分佈式系統是相通的。

哈希分片:這種方法實現簡單,均衡性較好,但是集羣不易擴展。
一致性哈希:這種方案均衡性好,集羣擴展容易,只是實現複雜。代表有 Amazon 的 DynamoDB 和開源的 Cassandra。
範圍劃分:通常配合全局有序,複雜度在於合併和分裂。代表有 Hbase。


分片設計


分片設計簡單來說就是以什麼做分片,這是非常有技巧的,會直接影響寫入讀取的性能。

**結合時序數據庫的特點,根據 measurement+tags 分片是比較好的一種方式,因爲往往會按照一個時間範圍查詢,這樣相同 metric 和 tags 的數據會分配到一臺機器上連續存放,順序的磁盤讀取是很快的。**再結合上面講到的單機存儲內容,可以做到快速查詢。

進一步我們考慮時序數據時間範圍很長的情況,需要根據時間範圍再分成幾段,分別存儲到不同的機器上,這樣對於大範圍時序數據就可以支持併發查詢,優化查詢速度。

如下圖,第一行和第三行都是同樣的 tag(sensor=95D8-7913;city= 上海),所以分配到同樣的分片,而第五行雖然也是同樣的 tag,但是根據時間範圍再分段,被分到了不同的分片。第二、四、六行屬於同樣的 tag(sensor=F3CC-20F3;city= 北京)也是一樣的道理。

 


1.4 開源時序數據庫介紹


1.4.1開源時序數據庫對比


目前行業內比較流行的開源時序數據庫產品有 InfluxDB、OpenTSDB、Prometheus、Graphite等,其產品特性對比如下圖所示:

 


1.4.2 InfluxDB介紹


InfluxDB是一個開源的時序數據庫,使用GO語言開發,特別適合用於處理和分析資源監控數據這種時序相關數據。而InfluxDB自帶的各種特殊函數如求標準差,隨機取樣數據,統計數據變化比等,使數據統計和實時分析變得十分方便。

重要概念
influxdb裏面有一些重要概念:database,timestamp,field key, field value, field set,tag key,tag value,tag set,measurement, retention policy ,series,point。結合下面的例子數據來說明這幾個概念:

name: census
-————————————
time                     butterflies     honeybees     location   scientist
2015-08-18T00:00:00Z      12                23           1         langstroth
2015-08-18T00:00:00Z      1                 30           1         perpetua
2015-08-18T00:06:00Z      11                28           1         langstroth
2015-08-18T00:06:00Z      3                 28           1         perpetua
2015-08-18T05:54:00Z      2                 11           2         langstroth
2015-08-18T06:00:00Z      1                 10           2         langstroth
2015-08-18T06:06:00Z      8                 23           2         perpetua
2015-08-18T06:12:00Z      7                 22           2         perpetua

timestamp
既然是時間序列數據庫,influxdb的數據都有一列名爲time的列,裏面存儲UTC時間戳。

field key,field value,field set
butterflies和honeybees兩列數據稱爲字段(fields),influxdb的字段由field key和field value組成。其中butterflies和honeybees爲field key,它們爲string類型,用於存儲元數據。

而butterflies這一列的數據12-7爲butterflies的field value,同理,honeybees這一列的23-22爲honeybees的field value。field value可以爲string,float,integer或boolean類型。field value通常都是與時間關聯的。

field key和field value對組成的集合稱之爲field set。如下: 

butterflies = 12 honeybees = 23
butterflies = 1 honeybees = 30
butterflies = 11 honeybees = 28
butterflies = 3 honeybees = 28
butterflies = 2 honeybees = 11
butterflies = 1 honeybees = 10
butterflies = 8 honeybees = 23
butterflies = 7 honeybees = 22

在influxdb中,字段必須存在。注意,字段是沒有索引的。如果使用字段作爲查詢條件,會掃描符合查詢條件的所有字段值,性能不及tag。類比一下,fields相當於SQL的沒有索引的列。

tag key,tag value,tag set
location和scientist這兩列稱爲標籤(tags),標籤由tag key和tag value組成。location這個tag key有兩個tag value:1和2,scientist有兩個tag value:langstroth和perpetua。tag key和tag value對組成了tag set,示例中的tag set如下: 

location = 1, scientist = langstroth
location = 2, scientist = langstroth
location = 1, scientist = perpetua
location = 2, scientist = perpetua

tags是可選的,但是強烈建議你用上它,因爲tag是有索引的,tags相當於SQL中的有索引的列。tag value只能是string類型 如果你的常用場景是根據butterflies和honeybees來查詢,那麼你可以將這兩個列設置爲tag,而其他兩列設置爲field,tag和field依據具體查詢需求來定。

measurement
measurement是fields,tags以及time列的容器,measurement的名字用於描述存儲在其中的字段數據,類似mysql的表名。如上面例子中的measurement爲census。measurement相當於SQL中的表,本文中我在部分地方會用表來指代measurement。

retention policy
retention policy指數據保留策略,示例數據中的retention policy爲默認的autogen。它表示數據一直保留永不過期,副本數量爲1。你也可以指定數據的保留時間,如30天。

series
series是共享同一個retention policy,measurement以及tag set的數據集合。示例中數據有4個series,如下:

Arbitrary series number    Retention policy    Measurement    Tag set
series 1    autogen    census    location = 1,scientist = langstroth
series 2    autogen    census    location = 2,scientist = langstroth
series 3    autogen    census    location = 1,scientist = perpetua
series 4    autogen    census    location = 2,scientist = perpetua

 

point
point則是同一個series中具有相同時間的field set,points相當於SQL中的數據行。如下面就是一個point: 

name: census
-----------------
time                  butterflies    honeybees   location    scientist
2015-08-18T00:00:00Z       1            30           1        perpetua

database
上面提到的結構都存儲在數據庫中,示例的數據庫爲my_database。一個數據庫可以有多個measurement,retention policy, continuous queries以及user。influxdb是一個無模式的數據庫,可以很容易的添加新的measurement,tags,fields等。而它的操作卻和傳統的數據庫一樣,可以使用類SQL語言查詢和修改數據。

influxdb不是一個完整的CRUD數據庫,它更像是一個CR-ud數據庫。它優先考慮的是增加和讀取數據而不是更新和刪除數據的性能,而且它阻止了某些更新和刪除行爲使得創建和讀取數據更加高效。

更多詳細介紹請見:https://www.jianshu.com/p/a1344ca86e9b 

 

 

參考:

https://blog.csdn.net/liukuan73/article/details/79950329

http://www.infoq.com/cn/articles/storage-in-sequential-databases
https://zhuanlan.zhihu.com/p/32627177
https://segmentfault.com/a/1190000006868587
http://www.zhimengzhe.com/shujuku/MySQL/414763.html
https://blog.csdn.net/a464057216/article/details/53043551
https://blog.csdn.net/wudufeng/article/details/78567866
https://www.linuxdaxue.com/influxdb-basic-operation.html
https://www.jianshu.com/p/a1344ca86e9b 

http://www.zyiz.net/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章