06.25 五分鐘看懂時序數據庫

2017年時序數據庫忽然火了起來。開年2月Facebook開源了beringei時序數據庫;到了4月基於PostgreSQL打造的時序數據庫TimeScaleDB也開源了,而早在2016年7月,百度雲在其天工物聯網平臺上發佈了國內首個多租戶的分佈式時序數據庫產品TSDB,成為支持其發展製造,交通,能源,智慧城市等產業領域的核心產品,同時也成為百度戰略發展產業物聯網的標誌性事件。時序數據庫作為物聯網方向一個非常重要的服務,業界的頻頻發聲,正說明各家企業已經迫不及待的擁抱物聯網時代的到來。

本文會從時序數據庫的基本概念、使用場景、解決的問題一一展開,最後會從如何解決時序數據存儲這一技術問題入手進行深入分析。

1. 背景

百度無人車在運行時需要監控各種狀態,包括座標,速度,方向,溫度,溼度等等,並且需要把每時每刻監控的數據記錄下來,用來做大數據分析。每輛車每天就會採集將近8T的數據。如果只是存儲下來不查詢也還好(雖然已經是不小的成本),但如果需要快速查詢“今天下午兩點在後廠村路,速度超過60km/h的無人車有哪些”這樣的多緯度分組聚合查詢,那麼時序數據庫會是一個很好的選擇。

 2. 什麼是時序數據庫

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

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

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

 時序數據示例

五分鐘看懂時序數據庫

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-時序數據庫基本概念圖

 3. 時序數據庫的場景

所有有時序數據產生,並且需要展現其歷史趨勢、週期規律、異常性的,進一步對未來做出預測分析的,都是時序數據庫適合的場景。

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

在互聯網場景中,也有大量的時序數據產生。百度內部有大量服務使用天工物聯網平臺的時序數據庫。舉個例子,百度內部服務為了保障用戶的使用體驗,將用戶的每次網絡卡頓、網絡延遲都會記錄到百度天工的時序數據庫。由時序數據庫直接生成報表以供技術產品做分析,儘早的發現、解決問題,保證用戶的使用體驗。

 4. 時序數據庫遇到的挑戰

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

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

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

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

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

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

5. 數據的存儲

數據的存儲可以分為兩個問題,單機上存儲和分佈式存儲。

單機存儲

如果只是存儲起來,直接寫成日誌就行。但因為後續還要快速的查詢,所以需要考慮存儲的結構。

傳統數據庫存儲採用的都是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操作流程如下:

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

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

3. 隨著磁盤上積累的文件越來越多,會定時的進行合併操作,消除冗餘數據,減少文件數量。

五分鐘看懂時序數據庫

p4-Hbase LSM tree結構介紹(注1)

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

分佈式存儲

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

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

分片方法

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

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

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

範圍劃分:通常配合全局有序,複雜度在於合併和分裂。代表有Hbase。

分片設計

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

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

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

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

五分鐘看懂時序數據庫

p5-時序數據分片說明

6. 真實案例

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

InfluxDB:

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

這裡timestamp默認情況下是7天對齊,也就是說7天的時序數據會在一個Shard中。

五分鐘看懂時序數據庫

p6-Influxdb TSM結構圖(注2)

Kairosdb:

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

Cassandra有兩級索引:partition key和clustering key。其中partition key是其分片ID,使用的是一致性哈希;而clustering key在一個partition key中保證有序。

Kairosdb利用Cassandra的特性,將+++作為partition key,數據點時間在timestamp上的偏移作為clustering key,其有序性方便做基於時間範圍的查詢。

partition key中的timestamp是3周對齊的,也就是說21天的時序數據會在一個clustering key下。3周的毫秒數是18億正好小於Cassandra每行列數20億的限制。

OpenTsdb:

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

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

五分鐘看懂時序數據庫

上圖是OpenTsdb的row key組織方式。不同於別的時序數據庫,由於Hbase的row key全局有序,所以增加了可選的salt以達到更好的數據分佈,避免熱點產生。再由與timestamp間的偏移和數據類型組成column qualifier。

他的timestamp是小時對齊的,也就是說一個row key下最多存儲一個小時的數據。並且需要將構成row key的metric和tags都轉成對應的uid來減少存儲空間,避免Hfile索引太大。下圖是真實的row key示例。

五分鐘看懂時序數據庫

p7-open tsdb的row key示例(注3)

 7. 結束語

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

數據存儲是時序數據庫設計中很小的一塊內容,但也能管中窺豹,看到時序數據庫從設計之初就要考慮時序數據的特點。後續我們會從其他的角度進行討論。


分享到:


相關文章: