時序數據庫深入淺出之存儲篇——本質LSMtree,同時 metric(比如溫度)+tags 分片


什么是時序數據庫

先來介紹什么是時序數據。時序數據是基於時間的一系列的數據。在有時間的坐標中將這些數據點連成線,往過去看可以做成多緯度報表,揭示其趨勢性、規律性、異常性;往未來看可以做大數據分析,機器學習,實現預測和預警。

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

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

時序數據示例

p1- 北上廣三地 2015 年氣溫變化圖

p2- 北上廣三地當前溫度實時展現

下面介紹下時序數據庫的一些基本概念(不同的時序數據庫稱呼略有不同)。

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。

p3- 時序數據庫基本概念圖

 

時序數據庫遇到的挑戰

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

可以看到時序數據庫需要解決以下幾個問題

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

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

 

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

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

業界主流都是采用 LSM tree 替換 B tree,比如 Hbase, Cassandra 等 nosql 中。

 

分片設計

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

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

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

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

p5- 時序數據分片說明

真實案例

下面我以一批開源時序數據庫作為說明。

InfluxDB:

非常優秀的時序數據庫,但只有單機版是免費開源的,集群版本是要收費的。從單機版本中可以一窺其存儲方案:在單機上 InfluxDB 采取類似於 LSM tree 的存儲結構 TSM;而分片的方案 InfluxDB 先通過+(事實上還要加上 retentionPolicy)確定 ShardGroup,再通過+的 hash code 確定到具體的 Shard。

Kairosdb:

底層使用 Cassandra 作為分布式存儲引擎,如上文提到單機上采用的是 LSM tree。

OpenTsdb:

底層使用 Hbase 作為其分布式存儲引擎,采用的也是 LSM tree。

Hbase 采用范圍划分的分片方式。使用 row key 做分片,保證其全局有序。每個 row key 下可以有多個 column family。每個 column family 下可以有多個 column。

結束語

可以看到各分布式時序數據庫雖然存儲方案都略有不同,但本質上是一致的,由於時序數據寫多讀少的場景,在單機上采用更加適合大吞吐量寫入的單機存儲結構,而在分布式方案上根據時序數據的特點來精心設計,目標就是設計的分片方案能方便時序數據的寫入和讀取,同時使數據分布更加均勻,盡量避免熱點的產生。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM