時(shí)序數(shù)據(jù)庫(kù)之InfluxDB
最近公司業(yè)務(wù)重度依賴(lài)時(shí)序數(shù)據(jù)庫(kù), 公司上個(gè)版本選擇了OpenTSDB, 在1-2年前,他的確很流行。但是在做軟件重構(gòu)時(shí), 業(yè)務(wù)層反饋的一些問(wèn)題, OpenTSDB暫時(shí)無(wú)法解決,成為了一個(gè)痛點(diǎn), 讓我需要考慮其他方案, 由于之前使用過(guò)InfluxDB, 也一直在關(guān)注, 它給了我驚艷的感覺(jué),所以記憶猶新.
之前做運(yùn)維時(shí),重度使用過(guò)zabbix, 關(guān)系型數(shù)據(jù)庫(kù)的優(yōu)化,根本無(wú)法解決高IO, 后面又使用過(guò)Graphite, 這個(gè)安裝像迷一樣的工具, 它后端在RRD上面設(shè)計(jì)出了一個(gè)簡(jiǎn)單的時(shí)序數(shù)據(jù)庫(kù), 但是配置繁雜,容量完全靠規(guī)劃。直到使用了InfluxDB, 部署簡(jiǎn)單,使用方便,高壓縮, 對(duì)它印象很不錯(cuò), 但是0.12過(guò)后不支持集群。
之前InfluxDB切換了2次存儲(chǔ)引擎(它的存儲(chǔ)是插件式的), 也沒(méi)去了解過(guò)它切換的原因, 直到看到InfoQ上七牛的演講從InfluxDB看時(shí)序數(shù)據(jù)的處, 他道出了了原因:
-
LevelDB不支持熱備份, influxDB設(shè)計(jì)的shard會(huì)消耗大量文件描述符,將系統(tǒng)資源耗盡。
-
BoltDB解決了熱備, 解決了消耗大量文件描述符的問(wèn)題, 但是引入了一個(gè)更致命的問(wèn)題:容量達(dá)到數(shù)GB級(jí)別時(shí),會(huì)產(chǎn)生大量隨機(jī)寫(xiě), 造成高IOPS。
-
放棄了他們, 在他們的經(jīng)驗(yàn)上開(kāi)始自己實(shí)現(xiàn)一個(gè)存儲(chǔ)引擎: TSM(Time-Structured Merge Tree), 它截取了OpenTSDB的一些設(shè)計(jì)經(jīng)驗(yàn),根據(jù)LSM Tree針對(duì)時(shí)間序列數(shù)據(jù)進(jìn)行優(yōu)化
我認(rèn)為像這樣的針對(duì)特殊場(chǎng)景進(jìn)行優(yōu)化的數(shù)據(jù)庫(kù)會(huì)是今后數(shù)據(jù)庫(kù)領(lǐng)域發(fā)展的主流, 另一個(gè)證明就是EleasticSearch一個(gè)針對(duì)文本解索而設(shè)計(jì)的數(shù)據(jù)庫(kù), 雖然OpenTSDB也針對(duì)時(shí)序數(shù)據(jù)做了優(yōu)化,但是由于存儲(chǔ)系統(tǒng)依然依賴(lài)HBase, 所以力度上面感覺(jué)沒(méi)InfluxDB給力。
社區(qū)一路走來(lái)之艱辛,但是卻激情洋溢,他們是先行者. 我對(duì)它集群的閉源并不反感, 這群激情洋溢的人需要有商業(yè)支持。
這是DB Engine的時(shí)序數(shù)據(jù)庫(kù)最新的排行榜

上圖可以看出InfluxDB超級(jí)火熱, 穩(wěn)居第一,對(duì)于一個(gè)設(shè)計(jì)精良,部署簡(jiǎn)單,使用方便,而且還高性能的時(shí)序數(shù)據(jù)庫(kù)而言, 想不熱都難。
基于Go語(yǔ)言開(kāi)發(fā),社區(qū)非?;钴S,項(xiàng)目更新速度很快,日新月異,關(guān)注度高, 1.0發(fā)布過(guò)后, 穩(wěn)定性也非常高。官方是這樣介紹InfluxDB的:
influxdb是一個(gè)從底層一步一步成長(zhǎng)為能處理高寫(xiě)入,高查詢(xún)的時(shí)序數(shù)據(jù)庫(kù), 它專(zhuān)門(mén)針對(duì)時(shí)序數(shù)據(jù)做了優(yōu)化,讓其更高性能, 他可以用來(lái)存儲(chǔ)任何時(shí)序數(shù)據(jù), 包括DevOps的監(jiān)控、應(yīng)用指標(biāo)、物聯(lián)網(wǎng)傳感器的數(shù)據(jù), 并實(shí)時(shí)分析
這是它github上給出的特性說(shuō)明:
-
內(nèi)建HTTP API, 無(wú)需自己實(shí)現(xiàn)
-
數(shù)據(jù)高壓縮, 支持非常靈活的查詢(xún)?cè)L問(wèn)
-
支持類(lèi)SQL查詢(xún), 學(xué)習(xí)成本低, 方便使用
-
安裝和管理都十分簡(jiǎn)單, 數(shù)據(jù)寫(xiě)入和讀取的速度快
-
為實(shí)時(shí)查詢(xún)而生, 對(duì)每一個(gè)點(diǎn)位都建立索引, 及時(shí)查詢(xún)響應(yīng)速度小于100ms
我們需要一個(gè)時(shí)序數(shù)據(jù)庫(kù), 他需要能解決我們以下這些問(wèn)題:
-
一個(gè)測(cè)試指標(biāo)多值
一個(gè)指標(biāo)往往有多個(gè)維度來(lái)描述其變化狀態(tài),并不僅僅是值, 比如對(duì)于CPU的而言, 應(yīng)該有中斷,負(fù)載, 使用率等。
? ?2.多Tag支持
tag是對(duì)一個(gè)指標(biāo)的描述,是一個(gè)標(biāo)簽, 在業(yè)務(wù)上Tag對(duì)于分組過(guò)濾非常有意義, 用于標(biāo)示一個(gè)指標(biāo)在業(yè)務(wù)上的意義, 比如對(duì)于IOT來(lái)說(shuō), 傳感器的指標(biāo)往往是一個(gè)無(wú)意義的id, 因此需求給它打上name標(biāo)簽, 標(biāo)示他的特殊意義, 打上設(shè)備ID, 標(biāo)示它屬于哪個(gè)設(shè)備, 打上位置標(biāo)簽, 標(biāo)示該指標(biāo)來(lái)源于哪個(gè)地方。
? ? ? 3.在指標(biāo)的值上能做一些基本的比較運(yùn)算
作為一個(gè)數(shù)據(jù)庫(kù),在功能層面需要解決一些基本的運(yùn)算, 比如求和,求最小,求最大, 但這還不夠, 需要支持條件過(guò)濾, 支持Tag的條件過(guò)濾, 支持值的條件過(guò)濾, 支持值的條件過(guò)濾是關(guān)鍵, 不然會(huì)產(chǎn)生巨大的數(shù)據(jù)復(fù)制, 比如我們需要過(guò)濾出 CPU > 90的機(jī)器, 如果數(shù)據(jù)庫(kù)不支持, 那么我需要將這些數(shù)據(jù)從數(shù)據(jù)庫(kù)中查出來(lái),復(fù)制給我的程序處理。
這帶來(lái)了巨大的問(wèn)題:
-
數(shù)據(jù)庫(kù)要吐出如此大量的數(shù)據(jù), 負(fù)載升高, 出口流量暴增
-
程序拿到如此大量的數(shù)據(jù), 給處理方帶來(lái)了巨大的計(jì)算壓力, 如果前段采用Angular或者React來(lái)寫(xiě), 一個(gè)運(yùn)行在pc上的小小的瀏覽器,根本處理不了。
-
處理效率低,數(shù)據(jù)的處理本該在數(shù)據(jù)存儲(chǔ)的地方進(jìn)行, 比如Hadoop, 完全沒(méi)必要復(fù)制。
? ? 4.指標(biāo)計(jì)算的中間結(jié)果需要存會(huì)指標(biāo)
這是一個(gè)比較常見(jiàn)的場(chǎng)景, 使用RDD時(shí)更是常用,比如數(shù)據(jù)是按照30秒存儲(chǔ)的,但是我需要 這樣一個(gè)聚合維度 5m, 15m, 1h, 3h, 12h, 然后我平時(shí)只使用這些維度的數(shù)據(jù), 不用每次臨時(shí)計(jì)算。
influxDB的核心概念包含: Line Protocol, Retention Policy, Series, Point, Continuous Query.
5.1 Line Protocol
Line Protocol用于描述存入數(shù)據(jù)庫(kù)的數(shù)據(jù)格式, 也可以說(shuō)是數(shù)據(jù)協(xié)議, 相比于JSON格式,Line Protocol無(wú)需序列化,更加高效, 官方對(duì)它做了全面的介紹Line Protocol, 下面摘取語(yǔ)法部分做簡(jiǎn)要說(shuō)明:Line Protocol里面的一行就是InfluxDB里面的一個(gè)點(diǎn)位, 他將一個(gè)點(diǎn)分割成measurement, tag_set, field_set, timestamp4個(gè)部分, 例如:

-
measurement: metric name, 需要監(jiān)控的指標(biāo)的名稱(chēng), 比如上面的weather
-
tag_set: 使用”,”與measurement隔開(kāi), 表示一組Tag的集合, 用于保存點(diǎn)位的元數(shù)據(jù), 為可選項(xiàng), 會(huì)進(jìn)行索引,方便查詢(xún)時(shí)用于過(guò)濾條件, 格式: =,=, 比如上面的location=us-midwest
-
field_set: 使用空格與tag_set隔開(kāi), 標(biāo)示一組Field的集合, 用于保存該點(diǎn)位多維度的值, 支持各種類(lèi)型,數(shù)據(jù)存儲(chǔ)時(shí)不會(huì)進(jìn)行索引,格式: =,=, 比如上面的temperature=82
-
timestamp: 采集該點(diǎn)位的時(shí)間戳, 時(shí)間的默認(rèn)精度是納秒.
存儲(chǔ)策略:measurements,tag keys,field keys,tag values全局存一份。field values和timestamps每條數(shù)據(jù)存一份。
5.2 Retention Policy
指數(shù)據(jù)的保存策略, 包含數(shù)據(jù)的保存時(shí)間和副本數(shù)(集群中的概念),默認(rèn)保存時(shí)間是永久,副本是1個(gè), 但是我們可以修改, 也可以創(chuàng)建新的保存策略
5.3 Series
InfluxDB中元數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)體, series相當(dāng)于是InfluxDB中元數(shù)據(jù)的集合,在同一個(gè)database中,retention policy、measurement、tag sets完全相同的數(shù)據(jù)同屬于一個(gè)series,同一個(gè)series的數(shù)據(jù)在物理上會(huì)按照時(shí)間順序排列存儲(chǔ)在一起。
series 的key為 measurement+所有tags的序列化字符串, 他保存著該series的Retention policy, Measurement,Tag set, 比如:

5.4 Point
InfluxDB中單條插入語(yǔ)句的數(shù)據(jù)結(jié)構(gòu)體, 用于保存點(diǎn)位的值的集合, 每一個(gè)Point通過(guò)series和timestamp進(jìn)行唯一標(biāo)示:

5.5 Schema
用于描述數(shù)據(jù)在InfluxDB的組織形式, InfluxDB的Schema十分簡(jiǎn)單由 這些概念組成:
-
databases
-
retention policies
-
series
-
measurements
-
tag keys
-
tag values
-
field keys
在操作數(shù)據(jù)庫(kù)的時(shí)候,需要知道這些概念。
5.6 Continuous Query
簡(jiǎn)稱(chēng)CQ, 是預(yù)先配置好的一些查詢(xún)命令,SELECT語(yǔ)句必須包含GROUP BY time(),influxdb會(huì)定期自動(dòng)執(zhí)行這些命令并將查詢(xún)結(jié)果寫(xiě)入指定的另外的measurement中。
利用這個(gè)特性并結(jié)合RP我們可以方便地保存不同粒度的數(shù)據(jù),根據(jù)數(shù)據(jù)粒度的不同設(shè)置不同的保存時(shí)間,這樣不僅節(jié)約了存儲(chǔ)空間,而且加速了時(shí)間間隔較長(zhǎng)的數(shù)據(jù)查詢(xún)效率,避免查詢(xún)時(shí)再進(jìn)行聚合計(jì)算。
5.7 存儲(chǔ)引擎
從LevelDB(LSM Tree),到BoltD(mmap B+樹(shù)),現(xiàn)在是自己實(shí)現(xiàn)的TSM Tree的算法,類(lèi)似LSM Tree,針對(duì)InfluxDB的使用做了特殊優(yōu)化。
5.7.1 Shard
Shard這個(gè)概念并不對(duì)普通用戶(hù)開(kāi)放,Shard也不是存儲(chǔ)引擎, 它在存儲(chǔ)引擎之上的一個(gè)概念, 存儲(chǔ)引擎負(fù)責(zé)存儲(chǔ)shard, 因此在講存儲(chǔ)引擎之前先講明shard。
在InfluxDB中按照數(shù)據(jù)的時(shí)間戳所在的范圍,會(huì)去創(chuàng)建不同的shard,每一個(gè)shard都有自己的存儲(chǔ)引擎相關(guān)文件,這樣做的目的就是為了可以通過(guò)時(shí)間來(lái)快速定位到要查詢(xún)數(shù)據(jù)的相關(guān)資源,加速查詢(xún)的過(guò)程,并且也讓之后的批量刪除數(shù)據(jù)的操作變得非常簡(jiǎn)單且高效。
它和retention policy相關(guān)聯(lián)。每一個(gè)存儲(chǔ)策略下會(huì)存在許多shard,每一個(gè)shard存儲(chǔ)一個(gè)指定時(shí)間段內(nèi)的數(shù)據(jù),并且不重復(fù),例如7點(diǎn)-8點(diǎn)的數(shù)據(jù)落入shard0 中,8點(diǎn)-9點(diǎn)的數(shù)據(jù)則落入shard1中。每一個(gè)shard都對(duì)應(yīng)一個(gè)底層的存儲(chǔ)引擎。
當(dāng)檢測(cè)到一個(gè)shard中的數(shù)據(jù)過(guò)期后,只需要將這個(gè)shard的資源釋放,相關(guān)文件刪除即可,這樣的做法使得刪除過(guò)期數(shù)據(jù)變得非常高效。
5.7.2 LevelDB
5.7.3 BoltDB
5.7.4 TSM Tree
6.1 安裝與部署
我這里主要做功能測(cè)試, 后面會(huì)有機(jī)會(huì)專(zhuān)門(mén)做性能測(cè)試, 因此這里使用官方提供的docker鏡像部署,官方鏡像最新也是1.2版本
配置Daocloud的鏡像加速源或者阿里的加速源,然后直接拉取鏡像
由于influxDB開(kāi)發(fā)時(shí)就設(shè)計(jì)好了, 官方也給出了環(huán)境配置變量,啟動(dòng)時(shí)可以通過(guò)這些環(huán)境變量對(duì)influxdb進(jìn)行配置InfluxDB配置
6.2 函數(shù)與SQL
內(nèi)部提供很多函數(shù),方便一些基本操作InfluxQL Functions

6.3 用戶(hù)認(rèn)證和權(quán)限
6.4 Retention Policy
6.5 Cotinuous Query
6.6 常見(jiàn)操作(SQL)
官方有很詳解的說(shuō)明,我這里僅截取出單節(jié)點(diǎn)部分:官方推薦硬件配置

根據(jù)負(fù)載情況官方推薦的硬件需求:
