[轉帖]時間序列數據庫 (TSDB)

時間序列數據庫 (TSDB)

https://www.jianshu.com/p/31afb8492eff

 

0.3392019.01.28 10:51:33字數 5598閱讀 4030

背景

2017年時序數據庫突然火了起來。開年2月Facebook開源了beringei時序數據庫;到了4月基於PostgreSQL打造的時序數據庫TimeScaleDB也開源了,而早在2016年7月,百度雲在其天工物聯網平臺上發佈了國內首個多租戶的分佈式時序數據庫產品TSDB,成爲支持其發展製造,交通,能源,智慧城市等產業領域的核心產品,同時也成爲百度戰略發展產業物聯網的標誌性事件。
例如:html

時間序列數據庫 Time Series Database (TSDB)

隨着分佈式系統監控、物聯網的發展,TSDB開始受到更多的關注。
維基百科上對於時間序列的定義是‘一系列數據點按照時間順序排列’mysql

時間序列數據就是歷史烙印,具備不變性,、惟一性、時間排序性git

時間序列數據跟關係型數據庫有太多不一樣,可是不少公司並不想放棄關係型數據庫。 因而就產生了一些特殊的用法,好比用 MySQL 的 VividCortex, 用 Postgres 的 Timescale。 不少人以爲特殊的問題須要特殊的解決方法,因而不少時間序列數據庫從頭寫起,不依賴任何現有的數據庫, 好比 GraphiteInfluxDBgithub

mysql 的引擎,除了常見的 innodb 和 myisam ,還有一個引擎叫 archive ,它的做用和 rrd 差很少,支持插入和查詢操做。web

  • 時序數據是基於時間的一系列的數據。在有時間的座標中將這些數據點連成線,往過去看能夠作成多緯度報表,揭示其趨勢性、規律性、異常性;往將來看能夠作大數據分析,機器學習,實現預測和預警。sql

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

數據寫入的特色

  • 寫入平穩、持續、高併發高吞吐:時序數據的寫入是比較平穩的,這點與應用數據不一樣,應用數據一般與應用的訪問量成正比,而應用的訪問量一般存在波峯波谷。時序數據的產生一般是以一個固定的時間頻率產生,不會受其餘因素的制約,其數據生成的速度是相對比較平穩的。
  • 寫多讀少:時序數據上95%-99%的操做都是寫操做,是典型的寫多讀少的數據。這與其數據特性相關,例如監控數據,你的監控項可能不少,可是你真正去讀的可能比較少,一般只會關心幾個特定的關鍵指標或者在特定的場景下才會去讀數據。
  • 實時寫入最近生成的數據,無更新:時序數據的寫入是實時的,且每次寫入都是最近生成的數據,這與其數據生成的特色相關,由於其數據生成是隨着時間推動的,而新生成的數據會實時的進行寫入。數據寫入無更新,在時間這個維度上,隨着時間的推動,每次數據都是新數據,不會存在舊數據的更新,不過不排除人爲的對數據作訂正。

數據查詢和分析的特色

  • 按時間範圍讀取:一般來講,你不會去關心某個特定點的數據,而是一段時間的數據。
  • 最近的數據被讀取的機率高
  • 歷史數據粗粒度查詢的機率搞
  • 多種精度查詢
  • 多維度分析

數據存儲的特色

  • 數據量大:拿監控數據來舉例,若是咱們採集的監控數據的時間間隔是1s,那一個監控項天天會產生86400個數據點,如有10000個監控項,則一天就會產生864000000個數據點。在物聯網場景下,這個數字會更大。整個數據的規模,是TB甚至是PB級的。
  • 冷熱分明:時序數據有很是典型的冷熱特徵,越是歷史的數據,被查詢和分析的機率越低。
  • 具備時效性:時序數據具備時效性,數據一般會有一個保存週期,超過這個保存週期的數據能夠認爲是失效的,能夠被回收。一方面是由於越是歷史的數據,可利用的價值越低;另外一方面是爲了節省存儲成本,低價值的數據能夠被清理。
  • 多精度數據存儲:在查詢的特色裏提到時序數據出於存儲成本和查詢效率的考慮,會須要一個多精度的查詢,一樣也須要一個多精度數據的存儲。

開源時間序列數據庫

RRDTool 是最先的時間序列數據庫,它自帶畫圖功能,如今大部分時間序列數據庫都使用Grafana來畫圖。數據庫

Graphite 是用 Python 寫的 RRD 數據庫,它的存儲引擎 Whisper 也是 Python 寫的, 它畫圖和聚合能力都強了不少,可是很難水平擴展。
OpenTSDB 使用 HBase 解決了水平擴展的問題
KairosDB 最初是基於OpenTSDB修改的,可是做者認爲兼容HBase致使他們不能使用不少 Cassandra 獨有的特性, 因而就拋棄了HBase僅支持Cassandra。
新發布的 OpenTSDB 中也加入了對 Cassandra 的支持。 故事還沒完,Spotify 的人原本想使用 KairosDB,可是以爲項目發展方向不對以及性能太差,就本身擼了一個 Heroic數組

InfluxDB 早期是徹底開源的,後來爲了維持公司運營,閉源了集羣版本。 在 Percona Live 上他們作了一個開源數據庫商業模型正面臨危機的演講,裏面調侃紅帽的段子很不錯。 而且今年的 Percona Live 還有專門的時間序列數據庫單元服務器

數據模型

時間序列數據能夠分紅兩部分

  • 序列 :就是標識符(維度),主要的目的是方便進行搜索和篩選
  • 數據點:時間戳和數值構成的數組
    • 行存:一個數組包含多個點,如 [{t: 2017-09-03-21:24:44, v: 0.1002}, {t: 2017-09-03-21:24:45, v: 0.1012}]
    • 列存:兩個數組,一個存時間戳,一個存數值,如[ 2017-09-03-21:24:44, 2017-09-03-21:24:45], [0.1002, 0.1012]
      通常狀況下:列存能有更好的壓縮率和查詢性能

基本概念

  • metric: 度量,至關於關係型數據庫中的table。
  • data point: 數據點,至關於關係型數據庫中的row。
  • timestamp:時間戳,表明數據點產生的時間。
  • field: 度量下的不一樣字段。好比位置這個度量具備經度和緯度兩個field。通常狀況下存放的是會隨着時間戳的變化而變化的數據。
  • tag: 標籤,或者附加信息。通常存放的是並不隨着時間戳變化的屬性信息。timestamp加上全部的tags能夠認爲是table的primary key。

以下圖,度量爲Wind,每個數據點都具備一個timestamp,兩個field:direction和speed,兩個tag:sensor、city。它的第一行和第三行,存放的都是sensor號碼爲95D8-7913的設備,屬性城市是上海。隨着時間的變化,風向和風速都發生了改變,風向從23.4變成23.2;而風速從3.4變成了3.3。

 

 

應用場景

全部有時序數據產生,而且須要展示其歷史趨勢、週期規律、異常性的,進一步對將來作出預測分析的,都是時序數據庫適合的場景。

例:
在工業物聯網環境監控方向,百度天工的客戶就遇到了這麼一個難題,因爲工業上面的要求,須要將工況數據存儲起來。客戶每一個廠區具備20000個監測點,500毫秒一個採集週期,一共20個廠區。這樣算起來一年將產生驚人的26萬億個數據點。假設每一個點50Byte,數據總量將達1P(若是每臺服務器10T的硬盤,那麼總共須要100多臺服務器)。這些數據不僅是要實時生成,寫入存儲;還要支持快速查詢,作可視化的展現,幫助管理者分析決策;而且也可以用來作大數據分析,發現深層次的問題,幫助企業節能減排,增長效益。最終客戶採用了百度天工的時序數據庫方案,幫助他解決了難題。
(這個高逼格)

時序數據庫遇到的挑戰

不少人可能認爲在傳統關係型數據庫上加上時間戳一列就能做爲時序數據庫。數據量少的時候確實也沒問題,但少許數據是展示的緯度有限,細節少,可置信低,更加不能用來作大數據分析。很明顯時序數據庫是爲了解決海量數據場景而設計的。

能夠看到時序數據庫須要解決如下幾個問題

  • 時序數據的寫入:如何支持每秒鐘上千萬上億數據點的寫入。

  • 時序數據的讀取:又如何支持在秒級對上億數據的分組聚合運算。

  • 成本敏感:由海量數據存儲帶來的是成本問題。如何更低成本的存儲這些數據,將成爲時序數據庫須要解決的重中之重。

這些問題不是用一篇文章就能含蓋的,同時每一個問題均可以從多個角度去優化解決。在這裏只從數據存儲這個角度來嘗試回答如何解決大數據量的寫入和讀取。

RRD

RRD (Round Robin Database)數據庫是一個環形的數據庫,數據庫由一個固定大小的數據文件來存放數據,此數據庫不會像傳統數據庫同樣爲隨着數據的增多而文件的大小也在增長,RRD在建立好後其文件大小就固定,能夠把它想像成一個圓,圓的衆多直徑把圓劃分紅一個個扇形,每一個扇形就是能夠存數據的槽位,每一個槽位上被打上了一個時間戳,在圓心上有一個指針,隨着時間的流逝,取回數據後,指針會負責把數據填充在相應的槽位上,當指針轉了360度後,最開始的數據就會被覆蓋,就這樣RRD循環填充着數據。

 

 
image.png

  • 源數據蒐集:採用一些數據蒐集工具,如腳本、shell命令、SNMP等工具在必定時間間隔裏把數據蒐集填充到rrd數據庫中,這些須要數據蒐集的對象叫DS,一個DS裏在一個時間裏能夠蒐集的數據能夠有多個,好比一個時間點上對網卡來講有進來的流量,也有流出的流量,因此這是2個數據成爲一組數據。
  • 臨時存儲:源數據獲取到後是存放在一個數據庫的一個臨時區域,這些源數據叫作PDP
  • 分組-聚合:RRDTool把這些PDP數據做爲數據源經過分組、再利用聚合函數計算後把計算後的結果放在RRD數據庫的時間槽(time slot)上,這些數據叫作CDP,CDP纔是RRDTool繪圖時真正打交道的數據,
  • 在從源數據中取數據作聚合計算時會有一個挑選數據的基準,也就是說是以幾個源數據爲一組作聚合,根據現實需求的不一樣,對源數據能夠很靈活的選擇不一樣的時間段提取源數據,再聚合提取不一樣的聚合值,這樣就產生不一樣組別的CDP數據,這些有以相同時間段挑選源數據及相同聚合函數計算的結果組成的數據就叫RRA,因此根據挑選源數據的標準及採用的聚合函數的不一樣,RRA能夠有多組。

  • DS:Data Source 數據源,用於定義蒐集數據的工具所蒐集數據的一些特性
  • Time Solt:時間槽,用於存放經過聚合後的數據區域
  • PDP:Primary Data Point 主數據節點,每一個時間點產生的數據,便是蒐集的源數據,沒有作聚合的數據
  • CDP(Consolidation Data Point 聚合數據節點):經過對獲取的源數據分組、聚合計算後獲得的數據叫CDP,
  • RRA(Round Robin Archive 輪轉歸檔):以相同的分組、聚合函數計算後的CDP數據組就組成了RRA
  • Resolution(解析度):這是一個時間跨度,表示在作聚合計算時是以幾個連續的time slot裏的數據作聚合,在默認時rrd是以300秒的間隔產生一個time slot。
  • CF:Consolidation Function,合併函數或聚合函數,以RRDTool中有AVERAGE、MAX、MIN、LAST4種

以一個圖來講明PDP、CDP、RRA之間的關係:

 

 

 

PDP是以規定的時間間隔(默認爲300秒)蒐集的源數據,第一個RRA以4個PDP(即4*300秒)爲一組作CF後組成的數據,第二個RRA則是以10個PDP爲一組作CF後組成的數據。

InfluxDB

InfluxDB 在存儲引擎上糾結了好久, leveldb, rocksdb, boltdb 都玩了個遍,最後決定本身造個輪子叫 Time Structured Merge Tree。

Time Structured Merge Tree (TSM) 和 Log Structured Merge Tree (LSM) 的名字都有點誤導性,關鍵並非樹,也不是日誌或者時間,而是 Merge。

  • 寫入的時候,數據先寫入到內存裏,以後批量寫入到硬盤。
  • 讀的時候,同時讀內存和硬盤而後合併結果。
  • 刪除的時候,寫入一個刪除標記,被標記的數據在讀取時不會被返回。
  • 後臺會把小的塊合併成大的塊,此時被標記刪除的數據才真正被刪除
  • 相對於普通數據,有規律的時間序列數據在合併的過程當中能夠極大的提升壓縮比。

熱點話題

存儲

單機存儲

若是隻是存儲起來,直接寫成日誌就行。但由於後續還要快速的查詢,因此須要考慮存儲的結構。
傳統數據庫存儲採用的都是B tree,這是因爲其在查詢和順序插入時有利於減小尋道次數的組織形式。咱們知道磁盤尋道時間是很是慢的,通常在10ms左右。磁盤的隨機讀寫慢就慢在尋道上面。對於隨機寫入B tree會消耗大量的時間在磁盤尋道上,致使速度很慢。咱們知道SSD具備更快的尋道時間,但並無從根本上解決這個問題。
對於90%以上場景都是寫入的時序數據庫,B tree很明顯是不合適的。
業界主流都是採用LSM tree替換B tree,好比Hbase, Cassandra等nosql中。這裏咱們詳細介紹一下。

LSM tree

LSM tree 包括內存裏的數據結構和磁盤上的文件兩部分,分別對應Hbase裏的MemStore和HLog;對應Cassandra裏的MemTable和sstable
LSM tree操做流程以下:

  1. 數據寫入和更新時首先寫入位於內存裏的數據結構。爲了不數據丟失也會先寫到WAL文件中。

  2. 內存裏的數據結構會定時或者達到固定大小會刷到磁盤。這些磁盤上的文件不會被修改。

  3. 隨着磁盤上積累的文件愈來愈多,會定時的進行合併操做,消除冗餘數據,減小文件數量。

 

分佈式存儲

分佈式存儲首先要考慮的是如何將數據分佈到多臺機器上面,也就是 分片(sharding)問題

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

  • 哈希分片:這種方法實現簡單,均衡性較好,可是集羣不易擴展。

  • 一致性哈希:這種方案均衡性好,集羣擴展容易,只是實現複雜。表明有Amazon的DynamoDB和開源的Cassandra。

  • 範圍劃分:一般配合全局有序,複雜度在於合併和分裂。表明有Hbase。

  • 結合時序數據庫的特色,根據metric+tags分片是比較好的一種方式,由於每每會按照一個時間範圍查詢,這樣相同metric和tags的數據會分配到一臺機器上連續存放,順序的磁盤讀取是很快的。

  • 考慮時序數據時間範圍很長的狀況,須要根據時間範圍再分紅幾段,分別存儲到不一樣的機器上,這樣對於大範圍時序數據就能夠支持併發查詢,優化查詢速度。

以下圖,第一行和第三行都是一樣的tag(sensor=95D8-7913;city=上海),因此分配到一樣的分片,而第五行雖然也是一樣的tag,可是根據時間範圍再分段,被分到了不一樣的分片。

 

 

InfluxDB的單機存儲

在單機上InfluxDB採起相似於LSM tree的存儲結構TSM;而分片的方案InfluxDB先經過<database>+<timestamp>(事實上還要加上retentionPolicy)肯定ShardGroup,再經過<metric>+<tags>的hash code肯定到具體的Shard。

低延遲

時間序列數據庫主要是用來分析的,因此提升響應速度對於診斷生產環境的問題是十分重要的。

把全部數據都放在內存

Facebook 寫了叫 Gorilla 的純內存時間序列數據庫發表在 VLDB 上,如今已經開源,更名爲 Beringei(都是猩猩…)

提早聚合

由於查詢中常常須要對一個很長的時間區間取一些粗粒度的值,好比6月到8月天天的平均CPU使用率。 這些聚合值(均值,最大,最小) 均可以在存儲數據的時候計算出來。BtrDB 和 Akumuli都在內部節點中存儲聚合值,這樣在不少查詢中底層的節點不須要被訪問就能夠獲得結果。

處理舊數據

  • 不少時間序列數據都沒有多大用處,特別是當系統長時間正常運行時,完整的歷史數據意義並不大。
  • 因此有些數據庫好比 RDDTool 和 Graphite 會自動刪除高精度的數據,只保留低精度的。
  • 可是對於不少新的時間序列數據庫,在聚合和刪除大量舊數據的同時保證系統正常運行並不像刪除一個本地文件那樣簡單。
  • 若是監控系統比被監控系統還不穩定就比較尷尬了。

元數據索引

  • 時間序列的標識符是時間序列數據庫裏主要的元數據。
  • Heroic 使用 Elasticsearch 來存儲元數據, 查詢首先經過 Elasticsearch 來取得符合要求的序列標識符,以後從 Cassandra 根據標識符來讀取對應的數據。
  • 可是維護一個完整的搜索引擎帶來的運維壓力和增長的通訊時間都是不能忽視的。
  • 所以 InfluxDB 和 Prometheus 就本身寫了倒排索引來索引元數據。

Tracing

  • InfluxDB 的人寫了一篇博客 Metrics are dead, 原由是在一個關於監控的會議 Monitorama 上有人說單純的監控數據已經不能知足他們複雜的微服務架構了。
  • 因而 InfluxDB 的人反駁說並非全部人都在使用大規模的分佈式系統,對於不少簡單的應用單純的監控數據已經徹底夠用了。
  • 個人見解是時間序列數據庫是能夠用來存 Trace 的。
  • Trace 是更加複雜的時間序列數據,把單純的數值變成一個包含更多信息的對象,它就是一個 Trace。
  • 而且不少流行的 Tracer 的存儲也是使用 Cassandra, 好比 Zipkin, Uber 的 Jaeger
  • InfluxDB 如今已經支持存儲 Trace 了

Ref:
https://zhuanlan.zhihu.com/p/29367404
https://github.com/xephonhq/awesome-time-series-database
https://blog.csdn.net/qq_33326449/article/details/79568014
https://zhuanlan.zhihu.com/p/32709932

相關文章
相關標籤/搜索