<!--一個部落客專欄付費入口結束-->
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
<div class="htmledit_views" id="content_views">
<p><span style="color:#333333;"><strong>摘要:</strong>2017年時序資料庫忽然火了起來。開年2月Facebook開源了beringei時序資料庫;到了4月基于PostgreSQL打造的時序資料庫TimeScaleDB也開源了,而早在2016年7月,百度雲在其天工物聯網平台上釋出了國内首個多租戶的分布式時序資料庫産品TSDB,成為支援其發展制造,交通,能源,智慧城市等産業領域的核心産品,同時...</span></p>
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先通過<database>+<timestamp>(事實上還要加上retentionPolicy)确定ShardGroup,再通過<metric>+<tags>的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的特性,将 <metric>+<timestamp>+<資料類型>+<tags>作為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. 結束語
可以看到各分布式時序資料庫雖然存儲方案都略有不同,但本質上是一緻的,由于時序資料寫多讀少的場景,在單機上采用更加适合大吞吐量寫入的單機存儲結構,而在分布式方案上根據時序資料的特點來精心設計,目标就是設計的分片方案能友善時序資料的寫入和讀取,同時使資料分布更加均勻,盡量避免熱點的産生。
資料存儲是時序資料庫設計中很小的一塊内容,但也能管中窺豹,看到時序資料庫從設計之初就要考慮時序資料的特點。後續我們會從其他的角度進行讨論。
作者:百度雲時序資料庫資深工程師
注1:來源http://tristartom.github.io/research.html
注2:來源http://blog.fatedier.com/2016/08/05/detailed-in-influxdb-tsm-storage-engine-one/
注3:來源http://opentsdb.net/docs/build/html/user_guide/backends/hbase.html
原文位址:https://blog.csdn.net/junlinbo/article/details/85055593