一、簡介
InfluxDB(時序數據庫)influxdb是一個開源分布式時序、時間和指標數據庫,使用 Go 語言編寫,無需外部依賴。其設計目標是實現分布式和水平伸縮擴展,是 InfluxData 的核心產品。常用的一種使用場景:監控數據統計,物聯網傳感器數據和實
時分析等的后端存儲。每毫秒記錄一下電腦內存的使用情況,然后就可以根據統計的數據,利用圖形化界面(InfluxDB V1一般配合Grafana)制作內存使用情況的折線圖;可以理解為按時間記錄一些數據(常用的監控數據、埋點統計數據等),然
后制作圖表做統計。
- 時間序列數據:從定義上來說,就是一串按時間維度索引的數據。
- 時序數據庫(TSDB)特點:
持續高並發寫入、無更新;
數據壓縮存儲;
低查詢延時。 - 常見 TSDB:influxdb、opentsdb、timeScaladb、Druid 等。
- influxdb 完整的上下游產業還包括:Chronograf、Telegraf、Kapacitor,其具體作用及關系如下:
influxdb和其他時序數據庫比較
二、同常見關系型數據庫(MySQL)的基礎概念對比
概念 | MySQL | InfluxDB |
---|---|---|
數據庫(同) | database | database |
表(不同) | table | measurement |
列(不同) | column | tag(帶索引的,非必須)、field(不帶索引)、timestemp(唯一主鍵) |
-
tag set:不同的每組tag key和tag value的集合;
-
field set:每組field key和field value的集合;
-
retention policy:數據存儲策略(默認策略為autogen)InfluxDB沒有刪除數據操作,規定數據的保留時間達到清除數據的目的;
-
series:共同retention policy,measurement和tag set的集合;
-
示例數據如下: 其中census是measurement,butterflies和honeybees是field key,location和scientist是tag key
name: census ———————————— time butterflies honeybees location scientist 2015-08-18T00:00:00Z 12 23 1 langstroth 2015-08-18T00:00:00Z 1 30 1 perpetua 2015-08-18T00:06:00Z 11 28 1 langstroth 2015-08-18T00:06:00Z 11 28 2 langstroth
- point的數據結構由時間戳(time)、標簽(tags)、數據(fields)三部分組成,具體含義如下:
point 屬性 | 含義 |
---|---|
time | 數據記錄的時間,是主索引(自動生成) |
tags | 各種有索引的屬性 |
fields | 各種value值(沒有索引的屬性) |
- 此外,influxdb還有個特有的概念:series(一般由:retention policy, measurement, tagset就共同組成),其含義如下:
所有在數據庫中的數據,都需要通過圖表來展示,而這個series表示這個表里面的數據,可以在圖表上畫成幾條線:通過tags排列組合算出來。 - 需要注意的是,influxdb不需要像傳統數據庫一樣創建各種表,其表的創建主要是通過第一次數據插入時自動創建,如下:
insert mytest, server=serverA count=1,name=5 //自動創建表
“mytest”,“server” 是 tags,“count”、“name” 是 fields - fields 中的 value 基本不用於索引
- tag 只能為字符串類型
- field 類型無限制
- 不支持join
- 支持連續查詢操作(匯總統計數據):CONTINUOUS QUERY
- 配合Telegraf服務(Telegraf可以監控系統CPU、內存、網絡等數據)
- 配合Grafana服務(數據展現的圖像界面,將influxdb中的數據可視化)
三、常見sql
-- 查看所有的數據庫 show databases; -- 使用特定的數據庫 use database_name; -- 查看所有的measurement show measurements; -- 查詢10條數據 select * from measurement_name limit 10; -- 數據中的時間字段默認顯示的是一個納秒時間戳,改成可讀格式 precision rfc3339; -- 之后再查詢,時間就是rfc3339標准格式 -- 或可以在連接數據庫的時候,直接帶該參數 influx -precision rfc3339 -- 查看一個measurement中所有的tag key show tag keys -- 查看一個measurement中所有的field key show field keys -- 查看一個measurement中所有的保存策略(可以有多個,一個標識為default) show retention policies;
- 1) 基於時間序列,支持與時間有關的相關函數(如最大,最小,求和等);
- 2) 可度量性:你可以實時對大量數據進行計算;
- 3) 基於事件:它支持任意的事件數據;
- 4) 無結構(無模式):可以是任意數量的列;
- 5)支持min, max, sum, count, mean, median 等一系列函數;
- 6)內置http支持,使用http讀寫;
- 7)強大的類SQL語法;
- 8)自帶管理界面,方便使用(新版本需要通過Chronograf)
四、 存儲引擎
采用TSM存儲引擎,TSM是在LSM的基礎上優化改善的,引入了serieskey的概念,對數據實現了很好的分類組織。
TSM主要由四個部分組成: cache、wal、tsm file、compactor:
- cache:插入數據時,先往 cache 中寫入再寫入wal中,可以認為 cache 是 wal 文件中的數據在內存中的緩存,cache 中的數據並不是無限增長的,有一個 maxSize 參數用於控制當 cache 中的數據占用多少內存后就會將數據寫入 tsm 文件。如果不配置的話,默認上限為 25MB
- wal:預寫日志,對比MySQL的 binlog,其內容與內存中的 cache 相同,作用就是為了持久化數據,當系統崩潰后可以通過 wal 文件恢復還沒有寫入到 tsm 文件中的數據,當 InfluxDB 啟動時,會遍歷所有的 wal 文件,重新構造 cache。
- tsm file:每個 tsm 文件的大小上限是 2GB。當達到 cache-snapshot-memory-size,cache-max-memory-size 的限制時會觸發將 cache 寫入 tsm 文件。
- compactor:主要進行兩種操作,一種是 cache 數據達到閥值后,進行快照,生成一個新的 tsm 文件。另外一種就是合並當前的 tsm 文件,將多個小的 tsm 文件合並成一個,減少文件的數量,並且進行一些數據刪除操作。 這些操作都在后台自動完成,一般每隔 1 秒會檢查一次是否有需要壓縮合並的數據。
InfluxDB數據保留策略:
- 每個數據庫剛開始會自動創建一個默認的存儲策略 autogen,數據保留時間為永久,在集群中的副本個數為1,之后用戶可以自己設置(查看、新建、修改、刪除),例如保留最近2小時的數據。插入和查詢數據時如果不指定存儲策略,則使用默認存儲策略,且默認存儲策略可以修改。InfluxDB 會定期清除過期的數據。
- 每個數據庫可以有多個過期策略:
show retention policies on "db_name" - Shard 在 influxdb中是一個比較重要的概念,它和 retention policy 相關聯。每一個存儲策略下會存在許多 shard,每一個 shard 存儲一個指定時間段內的數據,並且不重復,例如 7點-8點 的數據落入 shard0 中,8點-9點的數據則落入 shard1 中。每一個 shard 都對應一個底層的 tsm 存儲引擎,有獨立的 cache、wal、tsm file。
這樣做的目的就是為了可以通過時間來快速定位到要查詢數據的相關資源,加速查詢的過程,並且也讓之后的批量刪除數據的操作變得非常簡單且高效。 - 建議在數據庫建立的時候設置存儲策略,不建議設置過多且隨意切換
create database testdb2 with duration 30d
influxdb的數據存儲有三個目錄,分別是meta、wal、data:
- meta 用於存儲數據庫的一些元數據,meta 目錄下有一個 meta.db 文件;
- wal 目錄存放預寫日志文件,以 .wal 結尾;
- data 目錄存放實際存儲的數據文件,以 .tsm 結尾。
五、 性能優化與go開發
- 控制 series 的數量;
- 使用批量寫;
- 使用恰當的時間粒度;
- 存儲的時候盡量對 Tag 進行排序;
- 根據數據情況,調整 shard 的 duration;
- 無關的數據寫不同的database;
- 控制 Tag Key, 與 Tag Value 值的大小;
- 存儲分離 ,將 wal 目錄與 data 目錄分別映射到不同的磁盤上,以減少讀寫操作的相互影響。
- go語言開發只需要一個依賴包:github.com/influxdata/influxdb/client/v2,需要注意是v1.8版本,直接clone會失敗, 可先到:github.com/influxdata/influxdb中選擇版本號V1.8,然后clone下載
- 對influxdb的操作主要有連接、插入、查詢、關閉等幾個步驟,其中查詢的時候需要注意時間,要設置相應的時區,不然可能顯示的時間結果不同
import ( "github.com/influxdata/influxdb/client/v2" ... ) //連接influxdb func ConnectInflux()(client.Client, error){ conn, err := client.NewHTTPClient(client.HTTPConfig{ Addr:"http://localhost:8086", Username:username, Password:password, }) if nil != err{ fmt.Println(err) return nil, err } return conn, nil } //寫入point func WritePoints(con client.Client)error{ batchpoint ,err := client.NewBatchPoints(client.BatchPointsConfig{ Precision:"s", Database:MyDB, }) if nil != err{ fmt.Println(err) return err } record := Record{AssertId:"assert_aaaaa", ModelId:"model0", PoinntId:"point1", ModelPath:"model0/model1/point1", Attr:"", ModelTime:"123456789"} tags := map[string]string{Tag1:record.AssertId, Tag2:record.ModelId} fields := map[string]interface{}{Field1:record.PoinntId, Field2:record.ModelPath, Field3:record.Attr, Field4:record.ModelTime} point, err := client.NewPoint(Measurement, tags, fields, time.Now()) if nil != err{ fmt.Println(err) return err } batchpoint.AddPoint(point) if err := con.Write(batchpoint); err != nil{ fmt.Println(err) return err } } //查詢時要注意時區,東八區設置為:tz('Asia/Shanghai'),命令行需要:precision rfc3339 query := fmt.Sprintf("select * from %s limit %d tz('Asia/Shanghai')", Measurement, 5) res, err := querydb(conn, query)