influxdb 原理與應用

Green__Arrow發表於2018-08-06

一、基本概念
influxDB是一個由InfluxData開發的開源時序型資料庫。它由Go寫成,著力於高效能地查詢與儲存時序型資料。InfluxDB被廣泛應用於儲存系統的監控資料,IoT行業的實時資料等場景。
influxDB提供了類似SQL的查詢語言,並且可以設定資料儲存時間,支援基於http的資料插入和查詢,邏輯上由database(資料庫),measurement(一個字串表示該條記錄對應的含義),tag(索引欄位,按照字典序排序,比如型別或者渠道),field(欄位,比如條數或者金額等欄位)已經time(時間戳)組成;
influxDB除了這些基本的概念還包括point,series,shard這些概念;
1、point
influxDB中單條插入語句的資料結構,series+time可以用於區別一個point,point可以有多個filed name 和field value.
2、Series
Series 相當於influxDB中的一些資料集合,在同一個資料庫中,retention policy、measurement、tag sets完全相同的資料同屬於一個series,同一個series的資料在物理上會按照時間順序排列儲存在一起
series的key為measurement+ 所有的tags的序列化字串
Go中定義的結構
type Series struct {
mu sync.RWMutex
Key string // series key
Tags map[string]string // tags
id uint64 // id
measurement *Measurement // measurement
}
3、Shard
Shard 與retention policy 相關聯,通過它設定資料保留時間,當檢測到一個share中資料過期後,只需要將這個share的資源釋放,相關檔案刪除即可,每個儲存策略下會存多個share,每個share儲存一個指定時間段內的不重複資料,每個share都對應一個底層的tsm儲存引擎,有獨立的cache、wal、tsm file.

二、儲存引擎 -TSM Tree
從LevelDB(LSM Tree)到BoltDB(mmap B+樹),現在influxDB使用的是自己實現的TSM Tree的演算法,類似LSM Tree,針對InfluxDB的使用做了特殊優化,TSM Tree 是 InfluxDB 根據實際需求在 LSM Tree 的基礎上稍作修改優化而來。TSM 儲存引擎主要由幾個部分組成: cache、wal、tsm file、compactor。
1、cache
cache 相當於是 LSM Tree 中的 memtable,在記憶體中是一個簡單的 map 結構,這裡的 key 為 seriesKey + 分隔符 + filedName,目前程式碼中的分隔符為 #!~#,entry 相當於是一個按照時間排序的存放實際值的陣列,具體結構如下:
type Cache struct {
commit sync.Mutex
mu sync.RWMutex
store map[string]*entry
size uint64 // 當前使用記憶體的大小
maxSize uint64 // 快取最大值
// memtable 快照,用於寫入 tsm 檔案,只讀
snapshot *Cache
snapshotSize uint64
snapshotting bool
snapshotAttempts int
stats *CacheStatistics
lastSnapshot time.Time
}
插入資料時,實際上是同時往 cache 與 wal 中寫入資料,可以認為 cache 是 wal 檔案中的資料在記憶體中的快取。當 InfluxDB 啟動時,會遍歷所有的 wal 檔案,重新構造 cache,這樣即使系統出現故障,也不會導致資料的丟失。cache預設最大是25M,每當 cache 中的資料達到閥值後,會將當前的 cache 進行一次快照,之後清空當前 cache 中的內容,再建立一個新的 wal 檔案用於寫入,剩下的 wal 檔案最後會被刪除,快照中的資料會經過排序寫入一個新的 tsm 檔案中。
2、wal
wal 檔案的內容與記憶體中的 cache 相同,其作用就是為了持久化資料,當系統崩潰後可以通過 wal 檔案恢復還沒有寫入到 tsm 檔案中的資料。由於資料是被順序插入到 wal 檔案中,所以寫入效率非常高。但是如果寫入的資料沒有按照時間順序排列,而是以雜亂無章的方式寫入,資料將會根據時間路由到不同的 shard 中,每一個 shard 都有自己的 wal 檔案,這樣就不再是完全的順序寫入,對效能會有一定影響。wal 單個檔案達到一定大小後會進行分片,建立一個新的 wal 分片檔案用於寫入資料。
3、tsm file
單個 tsm file 大小最大為 2GB,用於存放資料。TSM file 使用了自己設計的格式,對查詢效能以及壓縮方面進行了很多優化。
4、compactor
compactor 元件在後臺持續執行,每隔 1 秒會檢查一次是否有需要壓縮合並的資料。
主要進行兩種操作,一種是 cache 中的資料大小達到閥值後,進行快照,之後轉存到一個新的 tsm 檔案中。
另外一種就是合併當前的 tsm 檔案,將多個小的 tsm 檔案合併成一個,使每一個檔案儘量達到單個檔案的最大大小,減少檔案的數量,並且一些資料的刪除操作也是在這個時候完成。

三、目錄與檔案結構
influxdb有三個目錄,data、meta 和 wal。
1、data 目錄下面是你建立的各種資料庫檔案,資料庫檔案下面是autogen資料夾,autogen下面是share儲存的不同時間段的資料,它的下一級就是具體的檔案已 .tsm 結尾的檔案 eg: 000000006-000000003.tsm;
2、meta 目錄用於儲存資料庫的一些後設資料,該目錄下面只有一個meta.db 檔案,當進行資料遷移過程中會用到。
3、wal 目錄存放預寫日誌檔案,目錄結構和data 結構一致,只是最後的檔案格式為 .wal 結尾 eg: _00006.wal
autogen 是儲存策略名稱,再下一層以數字命名的目錄是share的ID值,share儲存的某個時間段範圍內的資料。
4、wal 檔案
wal 檔案中的一條資料,對應的是一個 key(measument + tags + fieldName) 下的所有 value 資料,按照時間排序。
* Type (1 byte): 表示這個條目中 value 的型別。
* Key Len (2 bytes): 指定下面一個欄位 key 的長度。
* Key (N bytes): 這裡的 key 為 measument + tags + fieldName。
* Count (4 bytes): 後面緊跟著的是同一個 key 下資料的個數。
* Time (8 bytes): 單個 value 的時間戳。
* Value (N bytes): value 的具體內容,其中 float64, int64, boolean 都是固定的位元組數儲存比較簡單,通過 Type 欄位知道這裡 value 的位元組數。string 型別比較特殊,對於 string 來說,N bytes 的 Value 部分,前面 4 位元組用於儲存 string 的長度,剩下的部分才是 string 的實際內容。
5、TSM檔案
主要分為四個部分: Header, Blocks, Index, Footer。
Header包含magicNumber(用於區分儲存引擎)和version(引擎版本號);
Blocks內部是一些連續的block,它是influxdb中最小讀取物件,每次讀取操作都會讀取一個block,包含CRC32值(用於校驗date內容)和Data兩部分;
Index存放的是前面blocks裡面內容的索引,索引條目的順序先按照key 的字典序排序,再按照time排序,influxDB在做查詢操作時,可以根據index的資訊快速定位到tsm file中要查詢的 block 的位置。
type BlockIndex struct {
MinTime int64 //block 中 value 的最小時間戳
MaxTime int64 // block 中 value 的最大時間戳
Offset int64 //block 在整個 tsm file 中的偏移量
Size uint32 //block 的大小
}
type KeyIndex struct {
KeyLen uint16 //下面一個欄位 key 的長度
Key string //key 指的是 seriesKey + 分隔符 + fieldName
Type byte //fieldName 所對應的 fieldValue 的型別,也就是 Block 中 Data 內的資料的型別
Count uint32 //後面緊跟著的 Blocks 索引的個數
Blocks []*BlockIndex
}
type Index []*KeyIndex
間接索引只存在於記憶體中,是為了可以快速定位到一個 key 在詳細索引資訊中的位置而建立的,可以被用於二分查詢來實現快速檢索。offsets 是一個陣列,其中儲存的值為每一個 key 在 Index 表中的位置,由於 key 的長度固定為 2位元組,所以根據這個位置就可以找到該位置上對應的 key 的內容。
當指定一個要查詢的 key 時,就可以通過二分查詢,定位到其在 Index 表中的位置,再根據要查詢的資料的時間進行定位,由於 KeyIndex 中的 BlockIndex 結構是定長的,所以也可以進行一次二分查詢,找到要查詢的資料所在的 BlockIndex 的內容,之後根據偏移量以及 block 長度就可以從 tsm 檔案中快速讀取出一個 block 的內容。
Footer:tsm file 的最後8位元組的內容存放了 Index 部分的起始位置在 tsm file 中的偏移量,方便將索引資訊載入到記憶體中。

四、資料查詢與索引結構
由於 LSM Tree 的原理就是通過將大量的隨機寫轉換為順序寫,從而極大地提升了資料寫入的效能,與此同時犧牲了部分讀的效能。TSM 儲存引擎是基於 LSM Tree 開發的,所以情況類似。通常設計資料庫時會採用索引檔案的方式(例如 LevelDB 中的 Mainfest 檔案) 或者 Bloom filter 來對 LSM Tree 這樣的資料結構的讀取操作進行優化。
InfluxDB 中採用索引的方式進行優化,主要存在兩種型別的索引。
1、後設資料索引
一個資料庫的後設資料索引通過 DatabaseIndex 這個結構體來儲存,在資料庫啟動時,會進行初始化,從所有 shard 下的 tsm file 中載入 index 資料,獲取其中所有 Measurement 以及 Series 的資訊並快取到記憶體中。
type DatabaseIndex struct {
measurements map[string]*Measurement // 該資料庫下所有 Measurement 物件
series map[string]*Series // 所有 Series 物件,SeriesKey = measurement + tags
name string // 資料庫名
}
至此,我們在 o(1) 的時間複雜度內,獲取到了所有符合要求的 series key、這些 series key 所存在的 shardID,要查詢資料的時間範圍,之後我們就可以建立資料迭代器從不同的 shard 中獲取每一個 series key 在指定時間範圍內的資料。
2、TSM File 索引
上文中對於 tsm file 中的 Index 部分會在記憶體中做間接索引,從而可以實現快速檢索的目的。InfluxDB 中的所有資料讀取操作都通過 Iterator 來完成。

五、基本操作
1、建立資料庫: CREATE DATABASE mydb
2、展示資料庫或者表: SHOW databases show MEASUREMENTS
3、插入資料: INSERT cpu,host=serverA,region=us_west value=0.64
其中cpu 是measurement,tag是host和region ,value是欄位
4、查詢資料:SELECT host, region, value FROM cpu where host=‘serverA’
5、influxdb還可以使用http介面建立資料庫和寫資料
curl -i -XPOST http://localhost:8086/query –data-urlencode “q=CREATE DATABASE mydb”
6、InfluxDB提供了兩個特性——連續查詢(Continuous Queries簡稱CQ)和保留策略(Retention Policies簡稱RP),分別用來處理資料取樣和管理老資料的。例如建立一個保留52週資料RP:
CREATE RETENTION POLICY “a_year” ON “food_data” DURATION 52w REPLICATION 1
7、influxdb沒有顯示的刪除命令,依靠的是RP設定過期時間,也沒有顯示的跟新操作命令,這些換取了influxdb高效能的讀寫效能

六、Java api 介面
Influxdb提供了 java api jar包,包如下所示:

org.influxdb
influxdb-java
2.1

插入操作
InfluxDB client = InfluxDBFactory.connect(“http://localhost:8086“, “user”, “password”)
BatchPoints batchPoints = BatchPoints.database(dbName).consistency(InfluxDB.ConsistencyLevel.ALL) .build();
Point point1 = Point.measurement(“table_name”).useInteger(true)
.time(DataTamp, TimeUnit.SECONDS)
.field(“count”, count)
.field(“money”, money))
.tag(“type”, “”)
.tag(“country”, “”)
.build();
batchPoints.point(point1);
client.write(batchPoints);

查詢操作
String sql = “select sum(num) from table_name where time >= ‘’ and time<‘’ where type=‘’”;
Query query = new Query(sql, dbName);
QueryResult result = client.query(query);
series = result.getResults().get(0).getSeries();
if (series != null) {
Object resultSum = series.get(0).getValues().get(0).get(1);
if (resultSum != null) {
return Double.valueOf(resultSum.toString()).intValue();
}
}

七、資料遷移
當influxdb資料需要遷移機器時做的操作,資料遷移包含兩個部分,資料備份和資料恢復。
1、資料備份包含本地備份和遠端備份,一般進行都是遠端備份(跨機器)
本地備份
1.1 建立本地備份目錄 mkdir influxdb_backup cd ./influxdb_backup
1.2 備份後設資料 influxd backup -database mydatabase -retention autogen ./
1.3 備份資料庫 influxd backup -database testdb -retention autogen ./
遠端備份
假裝置份192.168.10.188的資料到192.168.10.199
注:備份192.168.10.188的資料,需要登入到192.168.10.199執行備份命令
1.1 建立備份目錄 mkdir backup_188 cd ./backup_188
1.2 備份後設資料 influxd backup -host 192.168.10.188:8088 ./
1.3 備份資料庫 influxd backup -database testdb -host 192.168.10.188:8088 ./

2、資料恢復(必須先恢復後設資料,再恢復資料庫中的資料)
a 恢復後設資料
在新機器上:
cd ./backup_188
influxd restore -metadir /var/lib/influxdb/meta ./
B 恢復資料庫中的資料
cd ./backup_188
influxd restore -database testdb -datadir /var/lib/influxdb/data ./
C 修改目錄許可權
chown -R influxdb:influxdb /var/lib/influxdb
D 重啟服務
service influxdb restart
注:上述中的/var/lib/influxdb/meta 和 /var/lib/influxdb/data 是InfluxDB執行配置檔案中配置的引數,詳見/etc/influxdb/influxdb.conf配置檔案meta 和 data 配置。

八、與Grafana結合使用
grafana 是一個開源的時序性統計和監控平臺,支援例如 elasticsearch、graphite、influxdb 等眾多的資料來源,並以功能強大的介面編輯器著稱。如果使用influxdb儲存監控的訂單資訊,可以選擇搭配grafana影像化介面監控各型別訂單資訊,這樣就可以實時的監控訂單的變化,官網地址https://grafana.com/ ,具體配置參考官方文件,這裡不做詳細介紹。

九、使用influxdb問題
1、在呼叫influxdb Java api 插入資料時 如果time和tag都一樣時候,會覆蓋舊值,這就會造成某個時間點某個業務資料缺失。
2、influxdb沒有顯式的刪除操作,只能依靠其過期策略。

參考文獻:
https://www.linuxdaxue.com/influxdb-principle.html
https://jasper-zhang1.gitbooks.io/influxdb/content/Introduction/getting_start.html
https://blog.csdn.net/qian_feifei/article/details/75139665

相關文章