实时数据库

发布时间 2023-11-20 08:55:13作者: 德琪

image-20231118153821343

数据存储-大数据的三种存储方式 - 知乎 (zhihu.com)

一、时序数据库概述

1.1 什么是时序数据库

​ 时序数据是一组按照时间维度索引的数据。时序数据在日常生活中随处可见,比如每个整点的温度、湿度等天气数据,每分钟的股票价格数据等。我们常用曲线图、柱状图等形式去展现时序数据,也就是我们常常听到的“数据可视化”。

​ 时序数据库是一种非关系型数据库,以时间作为数据主键,专门用来存储时序数据。

1.2 时序数据库的特点
  • 高压缩比:由于数据每分每秒都在变化,海量的时序数据往往体量巨大,占用大量硬件资源,所以需要优化数据压缩算法提高数据压缩比。
  • 高并发写入:时序数据库采用持续高并发写入数据,无更新的方式,对于时间相同的重复的数据,只保留一份数据。
  • 低延时、高并发查询:通过索引降低查询延时,通过缓存等技术提高数据并发能力。
1.3 时序数据库的使用场景
  • IOT行业:电力、化工等工业物联网数据监测
  • 金融行业:各类金融产品及其衍生品、数字货币数据存储与量化研究
  • IT行业:服务器、虚拟机、容器等的状态数据实时监测
  • 互联网行业:用户行为轨迹,日志等数据。

目前比较流行的时序数据库有:InfluxDB、Prometheus、OpenTSDB、TDengine等,其中使用最广泛的当属InfluxDB,行业内应用最广泛。还有就是刚进入业内视野的国产时序数据库TDengine。而Prometheus则是Prometheus监控系统自带的数据库。

二、InfluxDB简介

2.1 什么是InfluxDB

​ InfluxDB 是一个用于存储和分析时间序列数据的开源数据库。由 Golang 语言编写,也是由 Golang 编写的软件中比较著名的一个,在很多 Golang 的沙龙或者文章中可能都会把 InfluxDB 当标杆来介绍,这也间接帮助 InfluxDB 提高了知名度。

2.2 InfluxDB的特性

​ InfluxDB是一种时序数据高效读写、压缩存储、实时计算能力为一体的数据库服务,除了具有成本优势的高性能读、高性能写、高存储率,InfluxDB还具有如下特点:

  1. 无系统环境依赖,部署方便。
  2. 无结构化(SchemaLess)的数据模型,灵活强大。
  3. 原生HTTP管理接口,免插件配置和免第三方依赖。
  4. 强大的类SQL查询语句的操作接口,学习成本低,上手快。
  5. 丰富的权限管理功能,精细到“表”级别。
  6. 丰富的时效管理功能,自动删除过期数据,自定义删除指标数据。
  7. 低成本存储,采样时序数据,压缩存储。
  8. 丰富的聚合函数,支持AVG、SUM、MAX、MIN等聚合函数
2.3 InfluxDB几个基本概念

​ 例如:监控系统系统中,保存某个服务器的cpu和内存等资源使用情况,使用cpu_usage_total 的表名(measurement)保存数据。以下表示某一个point的样例数据:

image-20231118165645582

参考:

前言 · InfluxDB中文文档 (gitbooks.io)

彻底搞懂时序数据库InfluxDB,在SpringBoot整合InfluxDB-阿里云开发者社区 (aliyun.com)

InfluxDB安装使用介绍,小白向(附带安装包以及可视化工具安装包)_李欣峰的博客-CSDN博客

[InfluxDB--学习笔记 - 河图s - 博客园 (cnblogs.com)](https://www.cnblogs.com/qidaii/articles/17705431.html#:~:text=1 InfluxDB 1.8 在小版本上还在更新,主要是修复一些 BUG,不再添加新特性 2 InfluxDB 2.4,好,1.x 中的 database 到了 2.x 中变成了 bucket 等。)

2.4 InfluxDB2.0 的语法

​ InfluxDB 2.0 版本开始使用 Flux 语法,而不再支持 InfluxQL,这是一项重大变更。 Flux 是一种新的查询语言,它是基于函数式编程的,专门用于处理时间序列数据。相较于 InfluxQL,Flux 语法更加灵活、强大,可以更好地适配多变的、复杂的场景。下面是 InfluxQL 和 Flux 之间几个常见查询的对比。

1.查询测量值的具体值
InfluxQL:

SELECT mean(“field_name”) FROM “measurement_name” WHERE “tag_name” = ‘tag_value’ GROUP BY time(10m)

----------------------------------------------------------------------------------------------------------
Flux:

from(bucket: “bucket_name”)
|> range(start: -6h)
|> filter(fn: ® => r._measurement == “measurement_name” and r.tag_name == “tag_value”)
|> group(columns: [“_time”])
|> mean(column: “field_name”)
  1. from(bucket: "bucket_name"):指定从名为 “bucket_name” 的桶(数据存储单元)中读取数据。
  2. range(start: -6h):设定时间范围,表示查询过去6小时内的数据。start 参数指定时间范围的开始时间,这里使用了相对时间 “-6h” 表示当前时间往前推6个小时。
  3. filter(fn: (r) => r._measurement == "measurement_name" and r.tag_name == "tag_value"):根据条件过滤数据。fn 参数是一个函数,用于定义过滤条件,筛选出 _measurement 字段值为 “measurement_name”,并且 tag_name 字段值为 “tag_value” 的数据。
  4. group(columns: ["_time"]):按指定的列对数据进行分组。这里使用了 _time 字段来分组数据,即按时间间隔进行分组。
  5. mean(column: "field_name"):计算指定列的平均值。通过指定 column 参数为 “field_name”,计算该列的平均值。

​ 通过上述函数链式调用,Flux 依次执行每个函数操作从而实现查询逻辑。这样的函数式编程风格使得查询语句更加灵活、直观和易于理解,同时可以方便地添加、调整和组合多个操作来满足不同的需求。

​ 这里, InfluxQL 使用 SELECT 语句查询测量值的平均值。Flux 使用 filter() 函数选出符合条件的数据,再使用 group() 函数分组,最后再应用 mean() 函数计算平均值。

2.选择最大值和最小值
InfluxQL:

SELECT max(“field_name”) FROM “measurement_name” WHERE “tag_name” = ‘tag_value’
SELECT min(“field_name”) FROM “measurement_name” WHERE “tag_name” = ‘tag_value’

----------------------------------------------------------------------------------------------------------
Flux:

from(bucket: “bucket_name”)
|> range(start: -6h)
|> filter(fn: ® => r._measurement == “measurement_name” and r.tag_name == “tag_value”)
|> max(column: “field_name”)
from(bucket: “bucket_name”)
|> range(start: -6h)
|> filter(fn: ® => r._measurement == “measurement_name” and r.tag_name == “tag_value”)
|> min(column: “field_name”)

使用 Flux 语法,查询最大值和最小值可以分别用 max() 和 min() 函数实现。与 InfluxQL 不同,Flux 语句的每个步骤都可以链式地链接在一起。

3.进行多表联合查询
InfluxQL:

SELECT * FROM “measurement_name1” WHERE “tag_name” = ‘tag_value’
INNER JOIN “measurement_name2”
ON “measurement_name1”.“tag_name” = “measurement_name2”.“tag_name”
WHERE “measurement_name2”.“tag_name” = ‘tag_value’

----------------------------------------------------------------------------------------------------------
Flux:

from(bucket: “bucket_name”)
|> range(start: -6h)
|> filter(fn: ® => r._measurement == “measurement_name1” and r.“tag_name” == “tag_value”)
|> join(
tables: {name: “measurement_name2”,on:[“_tag1”]},
on:[“_tag1”],
fn: (table1,table2) => ({table1 with otherField: table2.someField})
)
|> filter(fn: ® => r._measurement == “measurement_name2” and r._field == “someField” and r._tag1 == “tag_value”)

​ 这里, InfluxQL 使用 INNER JOIN 操作符连接两个测量值。Flux 使用 join() 联结两个表,可以通过 fn 参数指定返回结果的格式,再使用 filter() 进行过滤。

​ 综上所述,虽然 InfluxQL 和 Flux 语法有很大的差异,但 Flux 语法更加灵活、强大,在处理时间序列数据时,具有更广泛的适用性。