之前介紹了運維監(jiān)控系統(tǒng)Prometheus,然后就有同鞋問我關(guān)于時序數(shù)據(jù)庫的情況,所以這里總結(jié)一下時序數(shù)據(jù)庫,并以InfluxDB為例,介紹時序數(shù)據(jù)庫的功能特性和使用方式,希望能對大家有所幫助。
一、時序數(shù)據(jù)庫概述1.1 什么是時序數(shù)據(jù)庫
時序數(shù)據(jù)是一組按照時間維度索引的數(shù)據(jù)。時序數(shù)據(jù)在日常生活中隨處可見,比如每個整點的溫度、濕度等天氣數(shù)據(jù),每分鐘的股票價格數(shù)據(jù)等。我們常用曲線圖、柱狀圖等形式去展現(xiàn)時序數(shù)據(jù),也就是我們常常聽到的“數(shù)據(jù)可視化”。
時序數(shù)據(jù)庫是一種非關(guān)系型數(shù)據(jù)庫,以時間作為數(shù)據(jù)主鍵,專門用來存儲時序數(shù)據(jù)。
1.2 時序數(shù)據(jù)庫的特點
- 高壓縮比:由于數(shù)據(jù)每分每秒都在變化,海量的時序數(shù)據(jù)往往體量巨大,占用大量硬件資源,所以需要優(yōu)化數(shù)據(jù)壓縮算法提高數(shù)據(jù)壓縮比。
- 高并發(fā)寫入:時序數(shù)據(jù)庫采用持續(xù)高并發(fā)寫入數(shù)據(jù),無更新的方式,對于時間相同的重復(fù)的數(shù)據(jù),只保留一份數(shù)據(jù)。
- 低延時、高并發(fā)查詢:通過索引降低查詢延時,通過緩存等技術(shù)提高數(shù)據(jù)并發(fā)能力。
1.3 時序數(shù)據(jù)庫的使用場景
- IOT行業(yè):電力、化工等工業(yè)物聯(lián)網(wǎng)數(shù)據(jù)監(jiān)測
- 金融行業(yè):各類金融產(chǎn)品及其衍生品、數(shù)字貨幣數(shù)據(jù)存儲與量化研究
- IT行業(yè):服務(wù)器、虛擬機、容器等的狀態(tài)數(shù)據(jù)實時監(jiān)測
- 互聯(lián)網(wǎng)行業(yè):用戶行為軌跡,日志等數(shù)據(jù)。
目前比較流行的時序數(shù)據(jù)庫有:InfluxDB、Prometheus、OpenTSDB、TDengine等,其中使用最廣泛的當(dāng)屬InfluxDB,行業(yè)內(nèi)應(yīng)用最廣泛。還有就是剛進入業(yè)內(nèi)視野的國產(chǎn)時序數(shù)據(jù)庫TDengine。而Prometheus則是Prometheus監(jiān)控系統(tǒng)自帶的數(shù)據(jù)庫。
二、InfluxDB簡介2.1 什么是InfluxDB
InfluxDB 是一個用于存儲和分析時間序列數(shù)據(jù)的開源數(shù)據(jù)庫。由 Golang 語言編寫,也是由 Golang 編寫的軟件中比較著名的一個,在很多 Golang 的沙龍或者文章中可能都會把 InfluxDB 當(dāng)標(biāo)桿來介紹,這也間接幫助 InfluxDB 提高了知名度。
2.2 InfluxDB的特性
- 內(nèi)置 HTTP 接口,使用方便
- 數(shù)據(jù)可以打標(biāo)記,這樣查詢可以很靈活
- 類 SQL 的查詢語句
- 安裝管理很簡單,并且讀寫數(shù)據(jù)很高效
- 能夠?qū)崟r查詢,數(shù)據(jù)在寫入時被索引后就能夠被立即查出
在最新的 DB-ENGINES 給出的時間序列數(shù)據(jù)庫的排名中,InfluxDB 高居第一位,可以預(yù)見,InfluxDB 會越來越得到廣泛的使用。
2.3 InfluxDB幾個基本概念
時序數(shù)據(jù)庫由于其存儲海量時序數(shù)據(jù)的特性,因此與傳統(tǒng)數(shù)據(jù)庫有些許不同,下面先對influxdb中涉及的基本概念作出解釋。
influxdb數(shù)據(jù)庫由database、measurement、point等三部分構(gòu)成。分別對應(yīng)關(guān)系數(shù)據(jù)庫中的數(shù)據(jù)庫、表、數(shù)據(jù)行。
- database:數(shù)據(jù)庫,同MySQL等關(guān)系型數(shù)據(jù)庫中的“數(shù)據(jù)庫Database”
- measurement:數(shù)據(jù)表,相當(dāng)于關(guān)系型數(shù)據(jù)庫中的“表Table”
- point:數(shù)據(jù)點,表示單條數(shù)據(jù)記錄,相當(dāng)于關(guān)系型數(shù)據(jù)庫中的“一行數(shù)據(jù)”
概念
MySQL
InfluxDB
數(shù)據(jù)庫(同)
database
database
表(不同)
table
measurement(測量; 度量)
列(不同)
column
Point,包括:tag(帶索引的,非必須)、field(不帶索引)、timestemp(唯一主鍵)
2.4 Point數(shù)據(jù)構(gòu)成
由于database和measurement與傳統(tǒng)數(shù)據(jù)庫基本相同,這里不做過多解釋,以下針對influxdb中特有的Point進行講解。
Point是InfluxDB中獨有的概念,由時間(time)、數(shù)據(jù)(field)、標(biāo)簽(tags)三類字段組成。
(1)time:代表每條數(shù)據(jù)的時間字段,是measurement中的數(shù)據(jù)主鍵,因此time字段具有索引屬性。一條point只能有一個time。
(2)field:代表各種數(shù)據(jù)的字段,例如氣溫、壓力、股價等,field字段沒有索引屬性。一條point可以包括多個field。
(3)tag:代表各類非數(shù)據(jù)字段,例如設(shè)備編碼、地區(qū)、姓名等,tag字段有索引屬性。一條point可以包括多個tag。
例如:監(jiān)控系統(tǒng)系統(tǒng)中,保存某個服務(wù)器的cpu和內(nèi)存等資源使用情況,使用cpu_usage_total 的表名(measurement)保存數(shù)據(jù)。以下表示某一個point的樣例數(shù)據(jù):
其中time為time字段,記錄數(shù)據(jù)產(chǎn)生的時間;cpu_usage和memory_usage分別代表CPU使用率和內(nèi)存使用率,因此他們是field字段,真正的監(jiān)控數(shù)據(jù);cpu 和host代表CPU的名字和服務(wù)器IP,所以,他們是tag字段,用于查詢和檢索。
在使用和設(shè)計InfluxDB數(shù)據(jù)結(jié)構(gòu)時,需要注意以下幾點:
- 1. tag 只能為字符串類型,可以加索引;
- 2. field 類型無限制,不能加索引;
- 3. InfluxDB不支持 join;
- 4. InfluxDB支持連續(xù)查詢操作(匯總統(tǒng)計數(shù)據(jù)):CONTINUOUS QUERY;
三、InfluxDB安裝
InfluxDB安裝非常簡單,根據(jù)操作系統(tǒng)執(zhí)行對應(yīng)的安裝命令即可。這里以window為例,演示如何安裝InfluxDB。
3.1 下載
InfluxDB:https://dl.influxdata.com/influxdb/releases/influxdb-1.7.4_windows_amd64.zip
chronograf :https://dl.influxdata.com/chronograf/releases/chronograf-1.7.8_windows_amd64.zip
chronograf為InfluxDB的Web后臺管理端,InfluxDB提供了控制臺命令端,如果使用不習(xí)慣,可以使用chronograf。
3.2 解壓安裝包
軟件下載成功后,解壓,我們可以看到influxDB的數(shù)據(jù)庫文件非常簡單。如下圖所示:
3.3 修改配置文件
InfluxDB 的數(shù)據(jù)存儲主要有三個目錄。默認(rèn)情況下是 meta, wal 以及 data 三個目錄,程序啟動后會自動生成。
- meta 用于存儲數(shù)據(jù)庫的一些元數(shù)據(jù),meta 目錄下有一個 meta.db 文件。
- wal 目錄存放預(yù)寫日志文件,以 .wal 結(jié)尾。
- data 目錄存放實際存儲的數(shù)據(jù)文件,以 .tsm 結(jié)尾。
接下來修改influxdb.conf 配置文件,修改以下部分的路徑。
另外,InfluxDB服務(wù)默認(rèn)端口為8086,如果需要更改端口號,則增加以下配置。
3.4 啟動InfluxDB服務(wù)
配置文件修改完成后,接下來啟動InfluxDB服務(wù)。直接運行Influxd.exe使用默認(rèn)配置運行即可。如果需要使用自定義的配置文件,則指定conf文件進行啟動,啟動命令如下:
#先cmd 進入influxDB目錄influxd.exe -config influxdb.conf
看到如下輸出,說明InfluxDB啟動成功。
四、InfluxDB使用
InfluxQL是一種類似于SQL的查詢語言,用于與InfluxDB進行交互。如果你使用過關(guān)系數(shù)據(jù)庫及SQL,那么你可以很快速的掌握InfluxQL。但是,InfluxQL又不完全是SQL,缺乏SQL中的一些高級的語法,例如UNION,JOIN,HAVING等。
那么InfluxDB的到底如何操作呢?接下來介紹InfluxQL語言的使用方法。
4.1 連接InfluxDB服務(wù)
進入到InfluxDB目錄后,在cmd中輸入influx命令即可,命令如下:
# 使用Command命令行進入influxdbinflux -port 8086
如果使用的是默認(rèn)配置,可以不需要加端口,直接influx即可。
4.2 操作InfluxDB
InfluxQL與SQL命令語法類似。接下來我們看一看InfluxQL 是怎么使用的?
4.2.1創(chuàng)建數(shù)據(jù)庫# 創(chuàng)建數(shù)據(jù)庫CREATE DATABASE weiz_tes# 顯示所有數(shù)據(jù)庫SHOW DATABASES# 刪除數(shù)據(jù)庫DROP DATABASE weiz_test# 使用數(shù)據(jù)庫USE weiz_test
4.2.2 表操作
1.創(chuàng)建表
InfluxDB沒有專門的創(chuàng)建表的命令,當(dāng)插入一條數(shù)據(jù)point至某A表時,此A表會自動創(chuàng)建,并且表的格式、字段名、字段類型也由此條插入命令決定。
2.修改表
InfluxDB沒有修改表的命令,但當(dāng)插入一條新數(shù)據(jù)point至表A時,如果此point中的字段多于原A表的字段,會自動修改A表與此條插入數(shù)據(jù)的格式字段等一致。
注意:此種情況僅限于新插入的數(shù)據(jù)字段與表A字段的交集即表A的情況,如果新插入數(shù)據(jù)字段與表A完全不同則會插入失敗。
3.查詢表
# 顯示該數(shù)據(jù)庫中的表SHOW MEASUREMENTS
4.刪除表:
DROP MEASUREMENT "measurementName"
5.插入數(shù)據(jù)
insert host_cpu_usage_total,host_name=host1,cpu_core=core1 cpu_usage=0.26,cpu_idle=0.76
上面,我們新增一條數(shù)據(jù),measurement為host_cpu_usage_total, tag為host_name,cpu_core, field為cpu_usage,cpu_idle。
我們簡單小結(jié)一下插入的語句寫法:
- 基本格式:.insert + measurement + "," + tag=value,tag=value +空格+ field=value,field=value ;
- tag與tag之間用逗號分隔;field與field之間用逗號分隔;
- tag與field之間用空格分隔;
- tag都是string類型,不需要引號將value包裹;
- field如果是string類型,需要加引號;
6.查詢數(shù)據(jù)
select * from host_cpu_usage_total
查詢語句使用select 關(guān)鍵字,格式與mysql 基本一致。
4.2.3 用戶管理
InfluxDB 默認(rèn)管理員賬號:admin,密碼為空。我們可以新增用戶和權(quán)限。命令如下:
#顯示用戶show users#創(chuàng)建用戶create user "username" with password 'password'#創(chuàng)建管理員權(quán)限用戶create user "username" with password 'password' with all privileges#刪除用戶drop user "username"
以上是對InfluxDB數(shù)據(jù)庫操作的基本總結(jié),其他復(fù)雜的用法可以參考官網(wǎng)教程。官網(wǎng)教程地址:https://docs.influxdata.com/influxdb/v1.7/。
五、SpringBoot整合InfluxDB
前面介紹了InfluxDB的基本安裝和使用。接下來我們介紹SpringBoot項目如何整合InfluxDB,實現(xiàn)數(shù)據(jù)的增刪改查。這里使用的Spring Boot版本為2.4.1。接下來看看如何實現(xiàn)的。
5.1 添加依賴
首先創(chuàng)建springboot項目spring-boot-starter-influxdb,并添加相關(guān)依賴,具體依賴如下:
org.springframework.bootspring-boot-starterorg.springframework.bootspring-boot-starter-testtestorg.influxdbinfluxdb-JAVA2.14
5.2 修改Application.properties 配置
接下來修改application.properties 配置文件,增加InfluxDB的相關(guān)配置,具體如下:
#influxdb 配置spring.influx.url=http://localhost:8086spring.influx.user=adminspring.influx.password=spring.influx.database=weiz_test
上面配置的是InfluxDB數(shù)據(jù)庫連接配置,默認(rèn)url為:http://localhost:8086 ,數(shù)據(jù)庫為之前創(chuàng)建的weiz_test數(shù)據(jù)庫。用戶名為admin,密碼默認(rèn)為空。
5.3 讀取配置文件
創(chuàng)建InfluxDBConfig類,負(fù)責(zé)讀取Influx的數(shù)據(jù)庫連接配置。具體代碼如下:
@Configurationpublic class InfluxDBConfig {@Value("${spring.influx.user}")public String userName;@Value("${spring.influx.password}")public String password;@Value("${spring.influx.url}")public String url;//數(shù)據(jù)庫@Value("${spring.influx.database}")public String database;
5.4 數(shù)據(jù)庫操作類
創(chuàng)建數(shù)據(jù)庫操作類InfluxDBService,負(fù)責(zé)數(shù)據(jù)庫的初始化,增刪改查等操作的具體實現(xiàn),示例代碼如下:
@Servicepublic class InfluxDBService {@Autowiredprivate InfluxDBConfig influxDBConfig;@PostConstructpublic void initInfluxDb() {this.retentionPolicy = retentionPolicy == null || "".equals(retentionPolicy) ? "autogen" : retentionPolicy;this.influxDB = influxDbBuild();//保留策略private String retentionPolicy;private InfluxDB influxDB;* 設(shè)置數(shù)據(jù)保存策略 defalut 策略名 /database 數(shù)據(jù)庫名/ 30d 數(shù)據(jù)保存時限30天/ 1 副本個數(shù)為1/ 結(jié)尾DEFAULT* 表示 設(shè)為默認(rèn)的策略public void createRetentionPolicy() {String command = String.format("CREATE RETENTION POLICY "%s" ON "%s" DURATION %s REPLICATION %s DEFAULT","defalut", influxDBConfig.database, "30d", 1);this.query(command);* 連接時序數(shù)據(jù)庫;獲得InfluxDBprivate InfluxDB influxDbBuild() {if (influxDB == null) {influxDB = InfluxDBFactory.connect(influxDBConfig.url, influxDBConfig.userName, influxDBConfig.password);influxDB.setDatabase(influxDBConfig.database);return influxDB;* 插入* @param measurement 表* @param tags 標(biāo)簽* @param fields 字段public void insert(String measurement, Map tags, Map fields) {influxDbBuild();Point.Builder builder = Point.measurement(measurement);builder.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS);builder.tag(tags);builder.fields(fields);influxDB.write(influxDBConfig.database, "", builder.build());* @desc 插入,帶時間time* @date 2021/3/27*@param measurement*@param time*@param tags*@param fields* @return voidpublic void insert(String measurement, long time, Map tags, Map fields) {influxDbBuild();Point.Builder builder = Point.measurement(measurement);builder.time(time, TimeUnit.MILLISECONDS);builder.tag(tags);builder.fields(fields);influxDB.write(influxDBConfig.database, "", builder.build());* @desc influxDB開啟UDP功能,默認(rèn)端口:8089,默認(rèn)數(shù)據(jù)庫:udp,沒提供代碼傳數(shù)據(jù)庫功能接口* @date 2021/3/13*@param measurement*@param time*@param tags*@param fields* @return voidpublic void insertUDP(String measurement, long time, Map tags, Map fields) {influxDbBuild();Point.Builder builder = Point.measurement(measurement);builder.time(time, TimeUnit.MILLISECONDS);builder.tag(tags);builder.fields(fields);int udpPort = 8089;influxDB.write(udpPort, builder.build());* 查詢* @param command 查詢語句* @returnpublic QueryResult query(String command) {influxDbBuild();return influxDB.query(new Query(command, influxDBConfig.database));* @desc 查詢結(jié)果處理* @date 2021/5/12*@param queryResultpublic List> queryResultProcess(QueryResult queryResult) {List> mapList = new ArrayList<>();List resultList = queryResult.getResults();//把查詢出的結(jié)果集轉(zhuǎn)換成對應(yīng)的實體對象,聚合成listfor(QueryResult.Result query : resultList){List seriesList = query.getSeries();if(seriesList != null && seriesList.size() != 0) {for(QueryResult.Series series : seriesList){List columns = series.getColumns();String[] keys = columns.toArray(new String[columns.size()]);List> values = series.getValues();if(values != null && values.size() != 0) {for(List value : values){Map map = new HashMap(keys.length);for (int i = 0; i < keys.length; i++) {map.put(keys[i], value.get(i));mapList.add(map);return mapList;* @desc InfluxDB 查詢 count總條數(shù)* @date 2021/4/8public long countResultProcess(QueryResult queryResult) {long count = 0;List> list = queryResultProcess(queryResult);if(list != null && list.size() != 0) {Map map = list.get(0);double num = (Double)map.get("count");count = new Double(num).longValue();return count;* 查詢* @param dbName 創(chuàng)建數(shù)據(jù)庫* @returnpublic void createDB(String dbName) {influxDbBuild();influxDB.createDatabase(dbName);* 批量寫入測點* @param batchPointspublic void batchInsert(BatchPoints batchPoints) {influxDbBuild();influxDB.write(batchPoints);* 批量寫入數(shù)據(jù)* @param database 數(shù)據(jù)庫* @param retentionPolicy 保存策略* @param consistency 一致性* @param records 要保存的數(shù)據(jù)(調(diào)用BatchPoints.lineProtocol()可得到一條record)public void batchInsert(final String database, final String retentionPolicy,final InfluxDB.ConsistencyLevel consistency, final List records) {influxDbBuild();influxDB.write(database, retentionPolicy, consistency, records);* @desc 批量寫入數(shù)據(jù)* @date 2021/3/19*@param consistency*@param recordspublic void batchInsert(final InfluxDB.ConsistencyLevel consistency, final List records) {influxDbBuild();influxDB.write(influxDBConfig.database, "", consistency, records);
5.5 測試驗證
接下來,我們寫幾個單元測試,驗證數(shù)據(jù)的增刪改查等操作是否成功。單元測試代碼如下:
@SpringBootTestclass Example01ApplicationTests {@Autowiredprivate InfluxDBService influxDBService;@Testvoid contextLoads() {@Testpublic void testSave(){String measurement = "host_cpu_usage_total";Map tags = new HashMap<>();tags.put("host_name","host2");tags.put("cpu_core","core0");Map fields = new HashMap<>();fields.put("cpu_usage",0.22);fields.put("cpu_idle",0.56);influxDBService.insert(measurement, tags, fields);@Testpublic void testGetdata(){String command = "select * from host_cpu_usage_total";QueryResult queryResult = influxDBService.query(command);List> result = influxDBService.queryResultProcess(queryResult);for (Map map: result) {System.out.println("time:"+ map.get("time")+" host_name:" + map.get("host_name")+" cpu_core:" + map.get("cpu_core")+" cpu_usage:" + map.get("host_name")+" cpu_idle:" + map.get("host_name"));
運行上面的新增和查詢等單元測試,單擊Run Test或在方法上右擊,選擇Run 'testSave' ,查看單元測試結(jié)果,運行結(jié)果如下圖所示。
接下來調(diào)用數(shù)據(jù)驗證數(shù)據(jù)查詢,運行'testGetData'測試方法,運行結(jié)果如下圖所示:
保存和查詢等功能的單元測試運行成功,說明InfluxDB的增加和查詢操作執(zhí)行成功。
最后
以上,我們就把時序數(shù)據(jù)庫InfluxDB介紹完了,并通過示例介紹了如何在SpringBoot項目中整合InfluxDB。示例代碼也會同步上傳:https://gitee.com/weizhong1988/spring-boot-starter 。如有疑問,請在下方留言!
InfluxDB在系統(tǒng)監(jiān)控、物聯(lián)網(wǎng)等方面的應(yīng)用越來越多,希望大家能夠熟練掌握。