一、基础概念

时序数据及时序数据库

时序数据简单的来说就是,一些数据描述了被测量的主体在时间范围内每个时间节点上的测量值,用于描述物体在历史时间维度上的转态变化信息。如在气象监测领域,数据时刻在变化,工作人员需要将这些数据的变化记录下来用作监控分析,因此采用在每一条数据记录上加上时间戳的方式,这些加了时间戳的数据就是时序数据。
一般来说,其有以下特点:

  • 是按照时间维度索引的数据;
  • 是一段时间内的测量值,测量值可以为多种类型;
  • 用来监控状态变化信息;
  • 数据量大,数据量随时间增加。

而时序数据库,顾名思义,就是为了处理时序数据而产生的数据库。

时序数据库的应用场景

  1. 在工业环境监控中应用;
  2. 在物联网 IoT 设备采集存储中的应用;
  3. 互联网业务性能监控服务;
  4. 在智能汽车中的应用等等

什么是 InfluxDB?

InfluxDB 是一个由 InfluxData 公司与 2013 年开发的开源分布式时间序列数据库,其设计意图就是为了能够存储带有大量时间戳的数据。有单机版和集群版,单机版开源免费,集群版付费。

InfluxDB 的基本概念

InfluxDB 有七个核心概念:

  • database:数据库。用户、保留策略、连续查询和时间序列数据的逻辑容器。
  • measurement:相当于关系型数据库中表的概念。可以理解为一条条记录都是存储于 measurement 中的,一个数据库可以有多个 measurement,一个 measurement 中可以存储很多的数据。
  • timestamp:时间戳。与 point 关联的日期和时间,每条记录都会带有一个单独的时间戳。
  • filed:未加索引的字段,用来存储具体的时序数据,即随着时间变化而变化的数据。是 InfluxDB 数据结构中记录元数据和实际数据的键值对,用来保存真实数据的结构。
  • tags:标签,一般用于存储标识数据来源的属性信息。是记录元数据的键值对,在 InfluxDB 的数据结构中是可选的,tags 和 filed 一样是 key-value 的结构,但会在 tags 上加索引。
  • point:一条记录。相当于关系型数据库中的一条记录。
  • series:InlufxDB 中一些数据的集合。在同一个 database 中,retention policy(保留策略)、measurement、tag 完全相同的数据属于一个 series,同一个 series 的数据在物理上会按照时间顺序排列存储在一起。

二、InfluxDB 的安装

这里只介绍在 Windows 下的安装,在生产环境中,一般都是在 Linux 下安装,此类安装教程在网络上有很多,推荐学习时使用 docker 安装。

1、首先进入官网

InfluxData Downloads
InfluxDB-安装influxdb01.png
选择 Doucmentation(官方文档),或者直接复制 wget 后面的连接:https://dl.influxdata.com/influxdb/releases/influxdb2-2.7.5-windows.zip 然后到浏览器中,会自动下载。

2、解压压缩包

将下载好的压缩包,解压到一个英文目录下即可。到此,服务端安装完成。
InfluxDB-安装influxdb02.png

3、服务端全局变量配置及测试

在全局系统环境变量 path 里加入 上一步解压的目录;
[InfluxDB-安装influxdb03.png]
打开cmd命令窗口使用命令,influxd version,正常显示版本信息即配置完成。
[InfluxDB-安装influxdb04.png]

4、InfluxDB 启动!

在命令窗口使用以下命令:influxd ,正常启动,会显示以下信息:
[InfluxDB-安装influxdb05.png]
打开浏览器,输入:http://localhost:8086/,第一次进入,会提示你注册,以及简要配置一些信息。
[InfluxDB-安装influxdb06.png]
点击 get started。
[InfluxDB-安装influxdb07.png]
填写相关信息,然后点击 CONTINUE。
[InfluxDB-安装influxdb08.png]
点击 continue 后,再点击 QUICK START 快速开始。
显示以下界面即配置完成:
[InfluxDB-安装influxdb09.png]

5、InfluxDB CLI 的安装及配置

打开网站:Install and use the influx CLI | InfluxDB Cloud (TSM) Documentation (influxdata.com)
[InfluxDB-安装influxdb10.png]
点击下载,然后将下载好的压缩包解压到一个英文目录下,再和安装 Influxd 服务端一样将解压目录添加到 path 下即可(图在配置服务端path那)。然后输入 influx 或者 influx version 如果显示下列信息,那么就安装完毕了。
[InfluxDB-安装influxdb11.png]

6、生成 TOKEN

如图,依次点击:Load Data-->API TOKENS-->GENERATE API TOKEN
[InfluxDB-安装influxdb12.png]
[InfluxDB-安装influxdb13.png]
All Access API Token:所有权限,相当于admin
Custom API Token:定制权限。
这里我们选择All Access API Token。
[InfluxDB-安装influxdb14.png]
然后我们点击save。注意,请妥善保存下方的 TOKEN,因为它无法出现第二次,到时候就要重新创建了。
[InfluxDB-安装influxdb15.png]
点击复制,至此,token生成完毕。

7、配置 CLI

到这里,CLI 还是不能使用的,因为它不知道服务端的地址,用户密码等,因此我们需要进行配置,指令如下:

influx config create --config-name influx_config --host-url "http://localhost:8086" --org "xiaoxiao" --token "myZQ0DpqZVnFYWYpR5N4Nx3qrNJRUs_1GPMouUQuutDOTLN8moCodNvR_XHwXP5SuCqwufYImZyKIjTUwP0AgA=="  --active

其中:

  • --config-name:配置文件名称
  • --host-url:服务端地址及端口
  • --org:组织名,也就是你注册时填写的那一栏
  • --token:令牌,上一步生成的token
    如果出现下方信息,则配置完成。
    [InfluxDB-安装influxdb16.png]

8、CLI 测试

输入指令:influx bucket list,如果出现下方信息,即配置成功。
[InfluxDB-CLI测试-查看桶列表.png]

9、InfluxDB 的卸载

InfluxDB 的卸载很简单,直接删掉InfluxDB的配置目录即可,输入命令 influxd print-config
[InfluxDB-查看服务端配置.png]
可以看到配置目录在 C:\Users\xiaoxiao\.influxdbv2 我们进入到这个目录,
[InfluxDB-influxdb配置目录.png]
这里就是 InfluxDB 配置目录,其中,保存的数据也在这里,如果想卸载,直接删掉这个目录就可以了。
最后,我们打开 configs 文件。
[InfluxDB-configs.png]
可以看到,我们刚刚配置的信息保存到这里了,你也可以在这里进行修改。
注:如果配置了环境变量,记得到PATH那删掉。

三、快速使用

这里介绍如何在Java中使用 InfluxDB 数据库。

1、启动 InfluxDB 服务

InfluxDB-启动 InfluxDB 服务.png

2、在 CLI 或者 UI 界面上创建一个桶

[InfluxDB-创建存储桶1.png]
按图示依次点击。
[InfluxDB-创建存储桶2.png]
这里我们选择 NEVER,这个的意思是,数据是否会自动删除。我们这里是测试,不需要自动删除,如果选择 OLDER THAN,并填写了删除日期,比如 24h,那么保存的数据就会在24h后自动删除。

3、创建 SpringBoot 工程

这里创建一个 springboot3 的 Maven 项目,直接创建即可。
[InfluxDB-创建SpringBoot工程.png]

然后导入 influxdb 的 Maven 依赖

<dependency>
  <groupId>com.influxdb</groupId>
  <artifactId>influxdb-client-java</artifactId>
  <version>6.6.0</version>
</dependency>

4、InflixDB在Java中的读写流程

写流程
  1. 获得 influxDBClient 实例对象;
  2. 得到 WriteApiBlocking 实例对象;
  3. 写入数据。
读流程
  1. 获得 influxDBClient 实例对象;
  2. 获得 QueryApi 实例对象;
  3. 编写 Flux 语句(详见第五章);
  4. 调用 QueryApi 的 query() 方法进行查询;
  5. 关闭 influxDBClient 实例对象。

5、相关配置及项目目录结构

本测试主要在 TEST 里进行。
[Influxdb-项目目录结构.png]
application.yml:

influx:  
  url: http://localhost:8086  
  user: admin  
  password: 123456789  
  bucket: my-bucket  
  org: xiaoxiao

6、使用 Java 在 InfluxDB 中写入数据

InfluxDB 的数据写入有 3 种方式:通过 Point 写入、通过行协议写入、通过实体类写入。
代码如下:
InfluxdbUtils.java:

@Component  
public class InfluxdbUtils {  
    @Value("${influx.url}")  
    String url;  
    @Value("${influx.user}")  
    String user;  
    @Value("${influx.password}")  
    String password;  
    @Value("${influx.bucket}")  
    String BUCKET;  
    @Value("${influx.org}")  
    String ORG;  
  
    private InfluxDBClient client;  
  
    @PostConstruct  
    public void init() {  
        client = InfluxDBClientFactory.create(url, user, password.toCharArray());  
    }  
  
    // Point 写入  
    public void writeDataV1 () {  
        WriteApiBlocking writeApi = client.getWriteApiBlocking();  
  
        Point point = Point.measurement("temperature")  
                .addTag("location", "west")  
                .addField("value", 55D)  
                .time(Instant.now(), WritePrecision.NS);  
  
        writeApi.writePoint(BUCKET, ORG, point);  
    }  
    
    // 行协议写入  
    public void writeDataV2 () {  
        WriteApiBlocking writeApi = client.getWriteApiBlocking();  
        writeApi.writeRecord(BUCKET, ORG, WritePrecision.NS,"temperature,location=north value=60.0");  
    }  
  
    // 实体类写入  
    public <T> void writeDataV3 (T data) {  
        WriteApiBlocking writeApi = client.getWriteApiBlocking();  
        writeApi.writeMeasurement(BUCKET, ORG, WritePrecision.NS, data); 
    }
}

接下来看看实体类是如何定义的:
Temperature.java

@Data  
@Measurement(name = "temperature")  
public class Temperature {  
    @Column(tag = true)  
    private String location;  
    @Column  
    private Double value;  
    @Column(timestamp = true)  
    private Instant time;  
}

测试类 InfluxdbDemoApplicationTests.java:

@Test  
void testWrite() {  
    Temperature temperature = new Temperature();  
    temperature.setLocation("south");  
    temperature.setValue(63.0);  
    temperature.setTime(Instant.now());  
      
    influxdbUtils.writeDataV1();  
    influxdbUtils.writeDataV2();  
    influxdbUtils.writeDataV3(temperature);  
}

然后我们到 Influx UI 上查看结果:
[Influxdb-结果查询.png]

7、使用 Java 查询 InfluxDB 中的数据

这里,queryApi 中有两类方法,一直是 query(),另一种是 queryRaw()。前者对 InfluxDB 执行 Flux 查询,并将整个响应同步映射到 List 中;后者则映射到字符串里。
在 InfluxdbUtils.java 中添加以下代码

public <T> T readData(String bucket, String startTime) {  
    QueryApi queryApi = client.getQueryApi();  
  
    String query =  """  
            from(bucket: "%s")           
                |> range(start: %s)
                """;  
    String flux = String.format(query, bucket, startTime);  
  
    List<FluxTable> tables = queryApi.query(flux, ORG);  
  
    for (FluxTable fluxTable : tables) {  
        List<FluxRecord> records = fluxTable.getRecords();  
        for (FluxRecord fluxRecord : records) {  
            System.out.println(fluxRecord.getTime() + ": " + fluxRecord.getValue());  
        }  
    }  
  
    return null;  
}

然后在测试类 InfluxdbDemoApplicationTests.java 添加:

@Test  
void testRead() {  
    influxdbUtils.readData("my-bucket", "-1h");  
}

点击运行,执行结果如下:
[InfluxDB-使用Java读取数据结果.png]
和我们在 UI 上查看到的一致。

关于更多的 API 我们可以通过 idea 进行查看(或者直接去官方文档),这里就不一一演示了。

8、使用 Java 创建 bucket 并添加权限

待补坑。

四、InfluxDB 数据保留策略

保留策略(Retention Policy)描述的是 InfluxDB 保存数据的时间,InfluxDB 会比较服务器本地的时间戳和存储数据里的时间戳之间的差值,然后根据这个差值进行判断,如果时间差值大于保留策略里面设置的值,就会删除这些过期的数据。
也就是我们前面创建 bucket 时,第二个选项:
[InfluxDB-influxdb数据保留策略.png]
关于修改,我们可以直接在 InfluxDB UI 上进行更改,
[InfluxDB-更改保留策略.png]

五、InfluxDB 数据处理语言 Flux

Flux 是一种功能性数据脚本语言,旨在将查询、处理、分析和对数据的操作统一到单一语法中,支持多种数据源类型,与时间序列数据库、关系型数据库、CSV等。
Flux 查询执行以下操作:首先从源中检索指定数量的数据,根据时间或列值过滤数据,然后将数据处理或塑造成预期的结果,最后将结果返回。

from(bucket: "example-bucket")
	|> range(start: -1d)
	|> filter(fn: (r) => r.measurement == "example-measurement")
	|> mean()
	|> yield(name: "_results")

其中各参数含义如下:

  • from():从某个数据源检索数据。
  • |>:管道转发运算符,作用是将每个函数的输出结果作为输入发送到下一个函数。
  • range()、filter():根据列值过滤数据。
  • mean():计算从数据源返回的值的平均值。

1、Flux 基本数据类型

主要有以下类型:Boolean(布尔值)、Bytes(字节)、Duration(持续时间)、String(字符串类型)、Time(时间类型)、Float(浮点类型)、Integer(整数类型)、Null(空值)。
同时 Float 和 Interger 都是 64 位的。
Duration 支持的时间单位如下:

单位含义单位含义
ns纳秒h小时
us微妙d
ms毫秒w星期
smo
dy

2、部分函数解析

from()函数
from(
	bucket: "example-bucket",
	host: "https://example.com",
	org: "example-org",
	token: "MyTokenCode",
)
  • bucket:存储桶名称。
  • host:数据库链接地址。
  • org:组织名。
  • token:操作数据库所需要的权限令牌。
range()函数

下列代码表示:统计前15分钟到系统当前时间的数据。

range(start:-15m, stop: now())

start表示开始时间,不填代表从无限远过去开始,即相当于填写 -(infinity);
stop表示结束时间,stop默认是当前时间, 即 now()。
start 和 stop 参数有以下填写方式:

  1. 绝对时间:使用自定义的时间格式字符串或时间戳,并配合 time() 函数使用。例如 start: time(v: "2024-04-22")stop: time(v: 1640995200000000000)
  2. 相对时间:使用相对于当前时间的时间长度。以负值表示过去的时间,以正值表示将来的时间。
    • start: -30d 表示30天前;
    • start: -1y 表示1年前;

六、结束语

好了,到这里,InfluxDB 的入门教程就结束了,你应该基本掌握了对于 InfluxDB 的查询、添加的操作。事实上,InfluxDB 还有一个叫 “连续查询” 的特色功能,集群功能以及“不推荐”使用的删除、更新数据的操作,本文没有写出,如果有可能,会在下一篇文章写出,当然你也可以参考 InfluxDB 的官方文档进行更深程度的学习InfluxDB OSS v2 Documentation (influxdata.com)。最后,感谢您的查阅。

天行健,君子以自强不息