一、简单对比
InfluxDB 是一个由 InfluxData 开发的开源时序型数据库。使用 GO 语言开发,特别适合用于处理和分析资源监控数据这种时序相关数据。
那么相比于关系型数据库有何优势?
1、写入性能提升
2、冷热数据分离
3、时间不可倒流,数据只写不改
二、基本概念
- Bucket(桶): Bucket 是 InfluxDB 中的基本存储单元,用于组织和存储时间序列数据。它是数据的逻辑容器,用于区分和隔离不同类型或来源的数据。
- Organization(组织): Organization 是 InfluxDB 中的组织概念,用于隔离和管理用户、应用程序或项目。每个用户可以属于一个或多个组织,Bucket 也属于一个组织。
- Measurement(测量值): Measurement 是 InfluxDB 中的数据表的概念。它类似于关系型数据库中的表,用于存储时间序列数据。每个 Measurement 包含一组字段和标签。
- Field(字段): Field 是 Measurement 中的一种数据类型,用于存储实际的数值数据。例如,温度、湿度等是字段的例子。
- Tag(标签): Tag 是 Measurement 中的一种索引类型,用于标识和过滤数据。标签通常用于存储维度信息,例如地理位置、设备 ID 等。
- Point(数据点): Point 是 InfluxDB 中时间序列数据的基本单位,它包含了时间戳、字段和标签。每个数据点都关联到一个 Measurement。
- API 密钥和访问令牌: 为了进行安全的访问和操作,InfluxDB 2.x 引入了 API 密钥和访问令牌。API 密钥用于身份验证,而访问令牌用于授权对数据的访问。
- Flux 查询语言: Flux 是 InfluxDB 2.x 中的查询语言,用于执行强大的数据处理和分析操作。它支持更灵活的查询、过滤、聚合和转换操作。
- 仪表板和可视化: InfluxDB 2.x 提供了仪表板和可视化工具,允许用户创建、定制和共享图表和仪表板,以直观地展示时间序列数据。
三、数据的存储
通过行协议写入数据
例如
occupancy_rate,cpu=core4 use=75,free=25

influxDB使用序列的方式去管理数据

图中的foodships为influxdb的measurement,相当于关系型数据库中的表
tags(图中的park_id,planet)相当于关系型数据库中的索引项
图中的#_foodships相当于关系型数据中的未建索引的列
在influxDB中,唯一的measurement、tag_set和filed(一个字段)组合是一个序列
比如tag有手机号,地块id,属性有经度、纬度、设备时间
那么该手机号地块号下的序列应该有三个,分别是经度序列,纬度序列,设备时间序列

假如我们有这样一个场景,我们需要查询一段时间的数据,对于传统的关系型数据库来说,我们很有可能需要多次寻址找到多个元组才能完成查询,而时序数据库是吧索引打到了一批次的数据上,在这种场景下的读写,时序数据库性能是远强于B+树数据库的
四、双索引设计
现在已经说明了基本的概念和数据的存储,但是还没有提到最重要的时间。在influxdb中,时间也是索引,数据在入库时,会按照时间戳进行排序。这样,我们在进行查询时,一般遵循下面的思路
(1)先指定要从哪个存储桶查询数据
(2)指定数据的时间范围
(3)指定measurement、tag_set和field说明我要查询哪个序列
五、flux查询语言
【示例】
from(bucket: "example_java")
|> range(start:2024-11-01T00:00:00Z, stop:2024-11-03T00:00:00Z)
|> filter(fn: (r) => r["cpu"] == "core1")

在上面的示例中我们看到了第一行指定了从哪个存储桶中查找,第二行指定了查询的数据的时间范围,第三行指定了查询的measurement,tag为cpu,但是因为没有过滤tag条件,我们查询出来了两条序列,而且每一行都是通过|> 符号将上一个函数的输出传递给下一个函数,类似于linux的管道
在range函数中,需要接收两个参数,start和stop,其中stop可以省略,省略的话默认为当前时间
start和stop既可以使用相对的时间区间也可以使用绝对的时间戳,在上面例子中使用的是绝对的时间戳,接下来我们将其换成相对的时间,其格式为时间间隔,如h/m/s
from(bucket: "example_java")
|> range(start:-3d)
|> filter(fn: (r) => r["_measurement"] == "occupancy_rate")

我们可以添加上tag的过滤条件,指定我们想要查询的序列
from(bucket: "example_java")
|> range(start:2024-11-01T00:00:00Z, stop:2024-11-03T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "occupancy_rate")
|> filter(fn: (r) => r["cpu"] == "core1")

这次只查询出了cpu为core1的序列
但是假如我们有多个属性,我们用这种方式查询到的会是这种形式
from(bucket: "example_java")
|> range(start:2024-11-01T00:00:00Z, stop:2024-11-03T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "occupancy_rate")
|> filter(fn: (r) => r["cpu"] == "core3")

可以看到,现在是长数据的格式,那么如果我们想让数据变得成宽数据格式,可以使用pivot函数
from(bucket: "example_java")
|> range(start:2024-11-01T00:00:00Z, stop:2024-11-03T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "occupancy_rate")
|> filter(fn: (r) => r["cpu"] == "core3")
|> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value")

其中 rowKey: [“time”]指定哪些列将用来标识唯一的行,通常使用时间戳列 “_time”-可以指定多个列
columnKey: [“_field”]指定哪些列的值将被转换为新的列名 这里指定 “field”,意味着 “_field” 列中的值将变成新的列名
valueColumn: "_value"指定哪一列包含实际的数据值,这些值将填充到新生成的列中
还有一些常见的函数
min(最小值) max(最大值), mean(平均值)
例如
from(bucket: "example_java")
|> range(start:2024-11-01T00:00:00Z, stop:2024-11-03T00:00:00Z)
|> filter(fn: (r) => r["_measurement"] == "occupancy_rate")
|> filter(fn: (r) => r["cpu"] == "core3")
|> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value")
|> max(column: "free")

六、spring boot应用
1、引入依赖
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-java</artifactId>
<version>7.2.0</version>
</dependency>
2、在配置文件中配置参数
spring:
influxdb:
url:
token:
bucket:
measurement:
org:
3、配置类
@Configuration
public class InfluxConfig {
@Value("${spring.influxdb.url}")

最低0.47元/天 解锁文章
1654

被折叠的 条评论
为什么被折叠?



