简介

InfluxDB 的使用场景

InfluxDB 是一种时序数据库,时序数据库通常被用在监控场景,比如运维和 IOT(物联网)领域。这类数据库旨在存储时序数据并实时处理它们。

比如。我们可以写一个程序将服务器上 CPU 的使用情况每隔 10 秒钟向 InfluxDB 中写入一条数据。接着,我们写一个查询语句,查询过去 30 秒 CPU 的平均使用情况,然后让这个查询语句也每隔 10 秒钟执行一次。最终,我们配置一条报警规则,如果查询语句的执行结果>xxx,就立刻触发报警。

上述就是一个指标监控的场景,在 IOT 领域中,也有大量的指标需要我们监控。比如, 机械设备的轴承震动频率,农田的湿度温度等等。

为什么不用关系型数据库

(1)写入性能

关系型数据库也是支持时间戳的,也能够基于时间戳进行查询。但是,从我们的使用场景出发,需要注意数据库的写入性能。通常,关系型数据库会采用 B+树数据结构,在数据写入时,有可能会触发叶裂变,从而产生了对磁盘的随机读写,降低写入速度。

当前市面上的时序数据库通常都是采用LSM Tree 的变种,顺序写磁盘来增强数据的写入能力。网上有不少关于性能测试的文章,同学们可以自己去参考学习,通常时序数据库都会保证在单点每秒数十万的写入能力。

(2)数据价值

我们之前说,时序数据库一般用于指标监控场景。这个场景的数据有一个非常明显的特点就是冷热差别明显。通常,指标监控只会使用近期一段时间的数据,比如我只查询某个设备最近 10 分钟的记录,10 分钟前的数据我就不再用了。那么这 10 分钟前的数据,对我们来说就是冷数据,应该被压缩放到磁盘里去来节省空间。而热数据因为经常要用,数据库就应该让它留在内存里,等待查询。而市面上的时序数据库大都有类似的设计。

(3)时间不可倒流,数据只写不改

时序数据是描述一个实体在不同时间所处的不同状态。

就像是我们打开任务管理器,查看 CPU 的使用情况。我发现 CPU 占用率太高了,于是杀死了一个进程,但 10 秒前的数据不会因为我关闭进程再发生改变了。

这是时序数据的一大特点。与之相应,时序数据库基本上是插入操作较多,而且还没有什么更新需求。

1.X 的 TICK 技术栈与 2.X 的进一步融合

根据上文的介绍,我们首先可以知道时序数据一般用在监控场景。大体上,数据的应用可以分为 4 步走。

  1. 数据采集

  2. 存储

  3. 查询(包括聚合操作)

  4. 报警

这样一看,只给一个数据库其实只能完成数据的存储和查询功能,上游的采集和下游的报警都需要自己来实现。因此 InfluxData 在 InfluxDB1.X 的时候推出了 TICK 生态来推出start 全套的解决方案。

TICK4 个字母分别对应 4 个组件。

  • T : Telegraf - 数据采集组件,收集&发送数据到 InfluxDB。

  • I : InfluxDB - 存储数据&发送数据到Chronograf。

  • C : Chronograf - 总的用户界面,起到总的管理功能。

  • K : Kapacitor - 后台处理报警信息。

MMSIZE

到了 2.x,TICK 进一步融合,ICK 的功能全部融入了 InfluxDB,仅需安装 InfluxDB 就能得到一个管理页面,而且附带了定时任务和报警功能。

influxDB 版本比较与选型

(1)版本特性比较

2020 年 InfluxDB 推出了 2.0 的正式版。2.x 同 1.x 相比,底层引擎原理相差不大,但会涉及一些概念的转变(例如 db/rp 换成了 org/bucket)。另外,对于 TICK 生态来说,1.x 需要自己配置各个组件。2.x 则是更加方便集成,有很棒的管理页面。

另外,在查询语言方面,1.x 是使用 InfluxQL 进行查询,它的风格近似 SQL。2.x 推出了 FLUX 查询语言,可以使用函数与管道符,是一种更符合时序数据特性的更具表现力的查询语言。

(2)选型,本文档使用 InfluxDB 2.4

  • 市场现状:目前企业里面用 InfluxDB 1.X 和 InfluxDB 2.X 都有人在用,数量上 InfluxDB1.X 占多一些。

  • 易用性:在开发中,InfluxDB 1.X 集成生态会比较麻烦,InfluxDB 2.X 相对来说更加便利。

  • 性能:InfluxDB 1.X 和 2.X 的内核原理基本一致,性能上差距不大。

  • 集群:InfluxDB 从 0.11 版本开始,就闭源了集群功能的代码。也就是说,你只能免费试用 InfluxDB 的单节点版( 开源), 想要集群等功能就需要购买企业版。不过就 InfluxDB 1.8 来说,有开源项目根据 0.11 的代码思路提供了 InfluxDB 开源的集群方案。也有开源项目给 InfluxDB 2.3 增加了反向代理功能,让我们可以横向拓展 InfluxDB 的服务能力。项目参考地址:

    InfluxDB Cluster 对应 1.8.10:https://github.com/chengshiwen/influxdb-cluster

    InfluxDB Proxy 对应 1.2 - 1.8:https://github.com/chengshiwen/influx-proxy

    InfluxDB Proxy 对应 2.3:https://github.com/chengshiwen/influx-proxy/tree/influxdb-v2

  • FLUX 语言支持:自 InfluxDB 1.7 和 InfluxDB 2.0 以来,InfluxDB 推出了一门独立的新的查询语言 FLUX,而且作为一个独立的项目来运作。InfluxData 公司希望 FLUX 语言能够成为一个像 SQL 一样的通用标准,而不仅仅是查询 InfluxDB 的特定语言。而且不管是你是选择 InfluxDB 1.X 还是 2.X 最终都会接触到FLUX。不过 2.X 对 FLUX 的支持性要更好一些。

  • InfluxDB 产品概况:

    • InfluxDB 1.8 在小版本上还在更新,主要是修复一些BUG,不再添加新特性

    • InfluxDB 2.4 这是 InfluxDB 较新的版本,仍然在增加新的特性。

    • InfluxDB 企业版 1.9 需要购买,相比开源版,它有集群功能。

    • InfluxDB Cloud,免部署,跑在 InfluxData 公司的云服务器上,你可以使用客户端来操作。功能上对应开源版的 2.4

  • 2.x 与 1.x 的主要区别:两个版本的内核原理基本一致,性能上的差别不大。差别主要是在,权限管理方式不同,2.x TICK 的集成性比 1.x 好,1.x 中的 database 到了 2.x 中变成了 bucket 等。

这里选择 Influx 2.4,学会使用 InfluxDB 2.4 后应当也能胜任 InfluxDB 1.7 及以上版本的开发。

安装部署 InfluxDB

下载安装

在 linux 环境下有两种安装方式:

  • 通过包管理工具安装,比如 apt 和yum

  • 直接下载可执行二进制程序的压缩包

这里选用第二种方式,可以使用下面的命令下载程序包:

wget https://dl.influxdata.com/influxdb/releases/influxdb2-2.4.0-linux-amd64.tar.gz

MMSIZE

压缩包下载好后,将其解压到目标路径。

 tar -zxvf influxdb2-2.4.0-linux-amd64.tar.gz -C /opt/module

Go 语言开发的项目一般来说会只打包成单独的二进制可执行文件,也就是解压后目录下的 influxd 文件,这一文件中全是编译后的本地码,可以直接跑在操作系统上,不需要安装额外的运行环境或者依赖。

MMSIZE

现在,可以运行使用下面的命令,正式开启 InfluxDB 服务进程。

 ./influxd

进行初始化配置

使用浏览器访问http://hadoop102:8086。如果是安装后的首次使用,InfluxDB 会返回一个初始化的引导界面。按照给定步骤完成操作就好。

(1)创建用户和初始化存储桶

点击GET STARTED 按钮,进入下一个步骤(添加用户)。如图所示,你需要填写、组织名称、用户名称、用户密码。

MMSIZE

填写完后点击CONTINUE 按钮进入下一步。

(2)配置完成

看到如图所示的页面,说明我们已经开始使用 tony 这一用户身份和InfluxDB 交互了。

MMSIZE

理论和原理

InfluxDB 行协议

Telegraf的内部数据结构叫做InfluxDB行协议。如下图所示:

Telegraf本身是InfluxData公司专门为InfluxDB开发的数据采集器。上面这种数据格式是InfluxDB数据库使用的,只要数据符合上面这种格式,就能通过InfluxDB的API将数据导入数据库。所以,自家的插件当然支持自家的生态了,InfluxDB。

与 CSV 相似,在 InfluxDB 行协议中,一条数据和另一条数据之间使用换行符分隔, 所以一行就是一条数据。另外,在时序数据库领域,一行数据一行数据由下面 4 种元素构成。

  1. measurement(测量名称)

  2. Tag Set(标签集)

  3. Field Set(字段集)

  4. Timestamp(时间戳)

接下来介绍一下它的几个构成部分。

(1)measurement(测量名称)

随着后面的学习,你会逐渐深入理解这个概念。目前,你可以将它理解为关系型数据库中的一张表。

  • 必需
  • 测量的名称。每个数据点都必须声明自己是哪个测量里面的 ,不可省略。
  • 大小写敏感
  • 不可以下划线 _ 开头

(2)Tag Set(标签集)

标签应该用在一些值的范围有限的,不太会变动的属性上。比如传感器的类型和id等等。在InfluxDB中一个Tag相当于一个索引。给数据点加上Tag有利于将来对数据进行检索。但是如果索引太多了,就会减慢数据的插入速度。

  • 可选
  • 键值关系使用 = 表示
  • 多个键值对之间使用英文逗号 , 分隔
  • 标签的键和值都区分大小写
  • 标签的键不能以下划线 _ 开头
  • 键的数据类型:字符串
  • 值的数据类型:字符串

(3)Field Set(字段集)

  • 必需
  • 一个数据点上所有的字段键值对,键是字段名,值是数据点的值。
  • 一个数据点至少要有一个字段。
  • 字段集的键是大小写敏感的。
  • 字段
  • 键的数据类型:字符串
  • 值的数据类型:浮点数 | 整数 | 无符号整数 | 字符串 | 布尔值

(4)Timestamp(时间戳)

  • 可选
  • 数据点的Unix时间戳,每个数据点都可以指定自己的时间戳。
  • 如果时间戳没有指定。那么InfluxDB就使用当前系统的时间戳。
  • 数据类型:Unix timestamp
  • 如果你的数据里的时间戳不是以纳秒为单位的,那么需要在数据写入时指定时间戳的精度。

(5)空格

行协议中的空格决定了InfluxDB如何解释数据点。第一个未转义的空格将测量值&Tag Set (标签集)与 Field Set(字段集) 分开。第二个未转义空格将Field Set(字段级)和时间戳分开。

(6)协议中的数据类型及其格式

1)Float(浮点数)

IEEE-754标准的64位浮点数。这是默认的数据类型。

示例:字段级值类型为浮点数的行协议

myMeasurement fieldKey=1.0
myMeasurement fieldKey=1
myMeasurement fieldKey=-1.234456e+78

2)Integer(整数)

有符号64位整数。需要在数字的尾部加上一个小写数字 i 。

整数最小值整数最大值
-9223372036854775808i9223372036854775807i

示例:字段值类型为有整数的

3)UInteger(无符号整数)

无符号64位整数。需要在数字的尾部加上一个小写数字 u 。

无符号整数最小值无符号整数最大值
0u18446744073709551615u

示例:字段值类型为无符号整数的航协议

myMeasurement fieldKey=1u
myMeasurement fieldKey=12485903u

4)String(字符串)

普通文本字符串,长度不能超过64KB

示例:

\# String measurement name, field key, and field value
myMeasurement fieldKey="this is a string"

5)Boolean(布尔值)

true或者false。

示例:

布尔值支持的语法
Truet, T, true, True, TRUE
Falsef, F, false, False, FALSE

示例:

myMeasurement fieldKey=true
myMeasurement fieldKey=false
myMeasurement fieldKey=t
myMeasurement fieldKey=f
myMeasurement fieldKey=TRUE
myMeasurement fieldKey=FALSE

不要对布尔值使用引号,否则会被解释为字符串

6)Unix Timestamp(Unix 时间戳)

如果你写时间戳,

myMeasurementName fieldKey="fieldValue" 1556813561098000000

(7)注释

以井号 # 开头的一行会被当做注释。

示例:

# 这是一行数据
myMeasurement fieldKey="string value" 1556813561098000000

常用概念

与传统数据库中的名词做比较:

influxDB中的名词传统数据库中的概念
database数据库
measurement数据库中的表
points表里面的一行数据

(1)Point

Point由时间戳(time)、数据(field)、标签(tags)组成。

Point相当于传统数据库里的一行数据,如下表所示:

Point属性传统数据库中的概念
time每个数据记录时间,是数据库中的主索引(会自动生成)
fields各种记录值(没有索引的属性)
tags各种有索引的属性

(2)Series

Series 相当于是 InfluxDB 中一些数据的集合,在同一个 database 中,retention policy、measurement、tag sets 、field完全相同的数据同属于一个 series,同一个 series 的数据在物理上会按照时间顺序排列存储在一起。

(3)Shard

Shard 在 InfluxDB 中是一个比较重要的概念,它和 retention policy 相关联。每一个存储策略下会存在许多 shard,每一个 shard 存储一个指定时间段内的数据,并且不重复,例如 7点-8点 的数据落入 shard0 中,8点-9点的数据则落入 shard1 中。每一个 shard 都对应一个底层的 tsm 存储引擎,有独立的 cache、wal、tsm file

这样做的目的就是为了可以通过时间来快速定位到要查询数据的相关资源,加速查询的过程,并且也让之后的批量删除数据的操作变得非常简单且高效。

在 LSM Tree 中删除数据是通过给指定 key 插入一个删除标记的方式,数据并不立即删除,需要等之后对文件进行压缩合并时才会真正地将数据删除,所以删除大量数据在 LSM Tree 中是一个非常低效的操作。

而在 InfluxDB 中,通过 retention policy 设置数据的保留时间,当检测到一个 shard 中的数据过期后,只需要将这个 shard 的资源释放,相关文件删除即可,这样的做法使得删除过期数据变得非常高效。

(4)Retention Policy

保留策略包括设置数据保存的时间以及在集群中的副本个数。

默认的 RP 为 default,保存时间不限制,副本个数为 1,默认 RP 是可以修改的,并且我们可以创建新的 RP。s

Prometheus 数据格式

Prometheus 也是一种时序数据库,不过它通常被用在运维场景下。Prometheus 是开放原子基金会的第二个毕业项目,这个基金会的第一个毕业项目就是大名鼎鼎的k8s。

同 InfluxDB 一样,Prometheus 也有自己的数据格式,只要数据符合这种格式就能被Prometheus 识别并写入数据库。而且 Prometheus 数据格式也是纯文本的。

近期 Prometheus技术热度高涨,有一个名为 OpenMetris 的数据协议越来越流行,它致力于让全球的指标监控有一样的数据格式,而这个数据协议就是根据 Prometheus 数据格式改的,两者 100%兼容,足以见其影响力。

Prometheus 数据格式主要包含四个元素:

  1. 指标名称(必需)

  2. 标签集(可选):标签集是一组键值对,键是标签的名称,值是具体的标签内容,而且值必须得是字符串。指标名称和标签共同组成索引。

  3. 值(必须):必须满足浮点数格式

  4. 时间戳(可选):Unix 毫秒级时间戳。

MSIZE

  • 第 1 个空格,将 指标名称&标签集与指标值 分隔开
  • 第 2 个空格,将 指标值与Unix 时间戳分隔开

时序数据库中的数据模型

想要正确使用时序数据库,就必须理解时序数据库管理数据的逻辑。这里,我们会和普通的 SQL(关系型)数据库做一下比较。

普通关系型数据库中的表

下面这张表示 SQL(关系型)数据库中一个简单的示例。表中有创建索引和未创建索引的列。

  • park_id、planet、time 是创建了索引的列。

  • _foodships 是未创建索引的列。

+---------+---------+---------------------+--------------+
| park_id | planet | time | #_foodships |
+---------+---------+---------------------+--------------+
| 1 | Earth | 1429185600000000000 | 0 |
| 1 | Earth | 1429185601000000000 | 3 |
| 1 | Earth | 1429185602000000000 | 15 |
| 1 | Earth | 1429185603000000000 | 15 |
| 2 | Saturn | 1429185600000000000 | 5 |
| 2 | Saturn | 1429185601000000000 | 9 |
| 2 | Saturn | 1429185602000000000 | 10 |
| 2 | Saturn | 1429185603000000000 | 14 |
| 3 | Jupiter | 1429185600000000000 | 20 |
| 3 | Jupiter | 1429185601000000000 | 21 |
| 3 | Jupiter | 1429185602000000000 | 21 |
| 3 | Jupiter | 1429185603000000000 | 20 |
| 4 | Saturn | 1429185600000000000 | 5 |
| 4 | Saturn | 1429185601000000000 | 5 |
| 4 | Saturn | 1429185602000000000 | 6 |
| 4 | Saturn | 1429185603000000000 | 5 |
+---------+---------+---------------------+--------------+
InfluxDB 中的数据表示

上面的数据,如果换到 InfluxDB 中,会换一种形式进行表示。

name: foodships
tags: park_id=1, planet=Earth
time #_foodships
---- ------------
2015-04-16T12:00:00Z 0
2015-04-16T12:00:01Z 3
2015-04-16T12:00:02Z 15
2015-04-16T12:00:03Z 15
name: foodships
tags: park_id=2, planet=Saturn
time #_foodships
---- ------------
2015-04-16T12:00:00Z 5
2015-04-16T12:00:01Z 9
2015-04-16T12:00:02Z 10
2015-04-16T12:00:03Z 14
name: foodships
tags: park_id=3, planet=Jupiter
time #_foodships
---- ------------
2015-04-16T12:00:00Z 20
2015-04-16T12:00:01Z 21
2015-04-16T12:00:02Z 21
2015-04-16T12:00:03Z 20
name: foodships
tags: park_id=4, planet=Saturn
time #_foodships
---- ------------
2015-04-16T12:00:00Z 5
2015-04-16T12:00:01Z 5
2015-04-16T12:00:02Z 6
2015-04-16T12:00:03Z 5
  • InfluxDB 中的 measurement(foodships)相当于SQL(关系型)数据库中的表

  • InfluxDB 中的 tags(park_id 和planet)相当于 SQL(关系型)数据库中的索引列

  • InfluxDB 中的 fileds(在这里是#_foodships)相当于 SQL(关系型)数据库中的未建索引的列。

  • InfluxDB 中的数据点2015-04-16T12:00:00Z 5相当于SQL(关系型)数据库中的一行。

理解序列的概念至关重要

简单来说,InfluxDB 这类数据库是用序列的方式来管理数据的。在 InfluxDB 中,唯一 的 measurement,tag_set 和 fileld(一个字段)组合是一个 series(序列)。比如下图中有 6 条连续的线,这里面每个条线就是一个序列。每一个序列的数据在内存和磁盘上紧密存放, 这样当你要查询这一序列的数据时,InfluxDB 可以很快定位到这一序列中的好多条数据。你也可以将measurement,tag,field 视为索引,而且它们本身就是索引。

MSIZE

以序列的方式管理数据是时序数据库和传统关系型数据库最不同的地方。传统的关系型数据库通常是以 record(记录或者行)的方式管理数据,这个时候,关系型数据库可以让你快速地通过索引定位到一条数据。

MMSIZE

但是在时序场景下,我们通常需要查找某个设备最近一段时间的数据。这个时候对于传统关系型数据库来说,很可能需要多次寻址来找到多个 record 才能完成查询。而时序库是把索引打到一批次的数据上,所以在这种场景的下的读写,时序库性能是远强于 B+树数据库的。

双索引设计与高效查询思路

我们之前说到你可以将 measurement、tag_set 和 field 视为索引,还没有提到最重要的时间。其实,在 InfluxDB 中时间也是索引,数据在入库时,会按时间戳进行排序。这样, 我们在进行查询时,一般遵循下面的思路。

  1. 先指定要从哪个存储桶查询数据

  2. 指定数据的时间范围

  3. 指定 measurement、tag_set、和 field 说明我要查询哪个序列。

MSIZE

我一次只能查询一个序列吗

一次只能查询一个序列,这显然是不合理的。

假如,我现在只指定要查询 measurent 为 m1 和 tag1 为 hello 的数据,那么就会命中图中 4 条序列。所以实际上,measurement,tag,field 都是倒排索引。

MSIZE

时间线膨胀(高基数问题)

时间线膨胀是所有时序数据库都绕不过的问题。简单地来解释时间线膨胀,就是我们的时序数据库中序列太多了。

当序列过多时,时序数据库的写入和读取性能通常都会有明显的下降。所以,当你去网上看一些时序数据库的压测文章时,需要注意文章有没有将序列数考虑进去。

存储引擎

从 LevelDB(LSM Tree),到 BoltDB(mmap B+树),现在是自己实现的 TSM Tree 的算法,类似 LSM Tree,针对 InfluxDB 的使用做了特殊优化。

LevelDB

LevelDB 底层使用了 LSM Tree 作为数据结构,用于存储大量的 key 值有序的 K-V 数据,鉴于时序数据的特点,只要将时间戳放入 key 中,就可以非常快速的遍历指定时间范围内的数据。LSM Tree 将大量随机写变成顺序写,所以拥有很高的写吞吐量,并且 LevelDB 内置了压缩功能。

数据操作被先顺序写入 WAL 日志中,成功之后写入内存中的 MemTable,当 MemTable 中的数据量达到一定阀值后,会转换为 Immutable MemTable,只读,之后写入 SSTable。SSTable 是磁盘上只读的用于存储有序键值对的文件,并且会持续进行合并,生成新的 SSTable。在 LevelDB 中是分了不同层级的 SSTable 用于存储数据。

LevelDB 不支持热备份,它的变种 RocksDB 和 HyperLevelDB 实现了这个功能。

最严重的问题是由于 InfluxDB 通过 shard 来组织数据,每一个 shard 对应的就是一个 LevelDB 数据库,而由于 LevelDB 的底层存储是大量 SSTable 文件,所以当用户需要存储长时间的数据,例如几个月或者一年的时候,会产生大量的 shard,从而消耗大量文件描述符,将系统资源耗尽。

BoltDB

之后 InfluxDB 采用了 BoltDB 作为数据存储引擎。BoltDB 是基于 LMDB 使用 Go 语言开发的数据库。同 LevelDB 类似的是,都可以用于存储 key 有序的 K-V 数据。

虽然采用 BoltDB 的写效率有所下降,但是考虑到用于生产环境需要更高的稳定性,BoltDB 是一个合适的选择,而且 BoltDB 使用纯 Go 编写,更易于跨平台编译部署。

最重要的是 BoltDB 的一个数据库存储只使用一个单独的文件。Bolt 还解决了热备的问题,很容易将一个 shard 从一台机器转移到另外一台。

但是当数据库容量达到数GB级别时,同时往大量 series 中写入数据,相当于是大量随机写,会造成 IOPS 上升。

TSM存储引擎

TSM Tree 是 InfluxDB 根据实际需求在 LSM Tree 的基础上稍作修改优化而来。

TSM 存储引擎主要由几个部分组成: cache、wal、tsm file、compactor。

MMSIZE

  • 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              // 缓存最大值
    
        // snapshots are the cache objects that are currently being written to tsm files
        // they're kept in memory while flushing so they can be queried along with the cache.
        // they are read only and should never be modified
        // memtable 快照,用于写入 tsm 文件,只读
        snapshot     *Cache
        snapshotSize uint64
        snapshotting bool
    
        // This number is the number of pending or failed WriteSnaphot attempts since the last successful one.
        snapshotAttempts int
    
        stats        *CacheStatistics
        lastSnapshot time.Time
    }
    

    插入数据时,实际上是同时往 cache 与 wal 中写入数据,可以认为 cache 是 wal 文件中的数据在内存中的缓存。当 InfluxDB 启动时,会遍历所有的 wal 文件,重新构造 cache,这样即使系统出现故障,也不会导致数据的丢失。

    cache 中的数据并不是无限增长的,有一个 maxSize 参数用于控制当 cache 中的数据占用多少内存后就会将数据写入 tsm 文件。如果不配置的话,默认上限为 25MB,每当 cache 中的数据达到阀值后,会将当前的 cache 进行一次快照,之后清空当前 cache 中的内容,再创建一个新的 wal 文件用于写入,剩下的 wal 文件最后会被删除,快照中的数据会经过排序写入一个新的 tsm 文件中。

  • WAL:wal 文件的内容与内存中的 cache 相同,其作用就是为了持久化数据,当系统崩溃后可以通过 wal 文件恢复还没有写入到 tsm 文件中的数据。

    由于数据是被顺序插入到 wal 文件中,所以写入效率非常高。但是如果写入的数据没有按照时间顺序排列,而是以杂乱无章的方式写入,数据将会根据时间路由到不同的 shard 中,每一个 shard 都有自己的 wal 文件,这样就不再是完全的顺序写入,对性能会有一定影响。看到官方社区有说后续会进行优化,只使用一个 wal 文件,而不是为每一个 shard 创建 wal 文件。

    wal 单个文件达到一定大小后会进行分片,创建一个新的 wal 分片文件用于写入数据。

  • TSM File:单个 tsm file 大小最大为 2GB,用于存放数据。

    TSM file 使用了自己设计的格式,对查询性能以及压缩方面进行了很多优化,在后面的章节会具体说明其文件结构。

  • Compactor:compactor 组件在后台持续运行,每隔 1 秒会检查一次是否有需要压缩合并的数据。

    主要进行两种操作:

    • 一种是 cache 中的数据大小达到阀值后,进行快照,之后转存到一个新的 tsm 文件中。
    • 另外一种就是合并当前的 tsm 文件,将多个小的 tsm 文件合并成一个,使每一个文件尽量达到单个文件的最大大小,减少文件的数量,并且一些数据的删除操作也是在这个时候完成。

目录与文件结构

InfluxDB 的数据存储主要有三个目录。

默认情况下是 meta, wal 以及 data 三个目录:

  • meta 用于存储数据库的一些元数据,meta 目录下有一个 meta.db 文件。

  • wal 目录存放预写日志文件,以 .wal 结尾。data 目录存放实际存储的数据文件,以 .tsm 结尾。这两个目录下的结构是相似的,其基本结构如下:

    # wal 目录结构
    -- wal
       -- mydb
          -- autogen
             -- 1
                -- _00001.wal
             -- 2
                -- _00035.wal
          -- 2hours
             -- 1
                -- _00001.wal
    
    # data 目录结构
    -- data
       -- mydb
          -- autogen
             -- 1
                -- 000000001-000000003.tsm
             -- 2
                -- 000000001-000000001.tsm
          -- 2hours
             -- 1
                -- 000000002-000000002.tsm
    

    其中 mydb数据库名称,autogen2hours 是存储策略名称,再下一层目录中的以数字命名的目录是 shard 的 ID 值,比如 autogen 存储策略下有两个 shard,ID 分别为 1 和 2,shard 存储了某一个时间段范围内的数据。再下一级的目录则为具体的文件,分别是 .wal.tsm 结尾的文件。

WAL 文件

MSIZE

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 的实际内容。
TSM 文件

单个 tsm 文件的主要格式如下:

MSIZE

主要分为四个部分: Header, Blocks, Index, Footer

其中 Index 部分的内容会被缓存在内存中,下面详细说明一下每一个部分的数据结构。

Header

MMSIZE

  • MagicNumber (4 bytes): 用于区分是哪一个存储引擎,目前使用的 tsm1 引擎,MagicNumber 为 0x16D116D1
  • Version (1 byte): 目前是 tsm1 引擎,此值固定为 1
Blocks

MMSIZE

Blocks 内部是一些连续的 Block,block 是 InfluxDB 中的最小读取对象,每次读取操作都会读取一个 block。每一个 Block 分为 CRC32 值和 Data 两部分,CRC32 值用于校验 Data 的内容是否有问题。Data 的长度记录在之后的 Index 部分中。

Data 中的内容根据数据类型的不同,在 InfluxDB 中会采用不同的压缩方式,float 值采用了 Gorilla float compression,而 timestamp 因为是一个递增的序列,所以实际上压缩时只需要记录时间的偏移量信息。string 类型的 value 采用了 snappy 算法进行压缩。

Data 的数据解压后的格式为 8 字节的时间戳以及紧跟着的 value,value 根据类型的不同,会占用不同大小的空间,其中 string 为不定长,会在数据开始处存放长度,这一点和 WAL 文件中的格式相同。

Index

MMSIZE

Index 存放的是前面 Blocks 里内容的索引。索引条目的顺序是先按照 key 的字典序排序,再按照 time 排序。InfluxDB 在做查询操作时,可以根据 Index 的信息快速定位到 tsm file 中要查询的 block 的位置。

这张图只展示了其中一部分,用结构体来表示的话类似下面的代码:

type BlockIndex struct {
    MinTime     int64
    MaxTime     int64
    Offset      int64
    Size        uint32
}

type KeyIndex struct {
    KeyLen      uint16
    Key         string
    Type        byte
    Count       uint32
    Blocks      []*BlockIndex
}

type Index []*KeyIndex
  • Key Len (2 bytes): 下面一个字段 key 的长度。
  • Key (N bytes): 这里的 key 指的是 seriesKey + 分隔符 + fieldName。
  • Type (1 bytes): fieldName 所对应的 fieldValue 的类型,也就是 Block 中 Data 内的数据的类型。
  • Count (2 bytes): 后面紧跟着的 Blocks 索引的个数。

后面四个部分是 block 的索引信息,根据 Count 中的个数会重复出现,每个 block 索引固定为 28 字节,按照时间排序。

  • Min Time (8 bytes): block 中 value 的最小时间戳。
  • Max Time (8 bytes): block 中 value 的最大时间戳。
  • Offset (8 bytes): block 在整个 tsm file 中的偏移量。
  • Size (4 bytes): block 的大小。根据 Offset + Size 字段就可以快速读取出一个 block 中的内容。
间接索引

间接索引只存在于内存中,是为了可以快速定位到一个 key 在详细索引信息中的位置而创建的,可以被用于二分查找来实现快速检索。

MMSIZE

offsets 是一个数组,其中存储的值为每一个 key 在 Index 表中的位置,由于 key 的长度固定为 2字节,所以根据这个位置就可以找到该位置上对应的 key 的内容。

当指定一个要查询的 key 时,就可以通过二分查找,定位到其在 Index 表中的位置,再根据要查询的数据的时间进行定位,由于 KeyIndex 中的 BlockIndex 结构是定长的,所以也可以进行一次二分查找,找到要查询的数据所在的 BlockIndex 的内容,之后根据偏移量以及 block 长度就可以从 tsm 文件中快速读取出一个 block 的内容。

Footer

MMSIZE

tsm file 的最后8字节的内容存放了 Index 部分的起始位置在 tsm file 中的偏移量,方便将索引信息加载到内存中。

InfluxDB 入门(借助 Web UI)

借助 Web UI,我们可以更好地理解 InfluxDB 的功能划分。接下来,我们就从 Web UI入手,先了解InfluxDB 的基本功能。

数据源相关

Load Data(加载数据)

MMSIZE

如图所示,页面上左侧的向上箭头,对应着 InfluxDB Web UI 的 Load Data(加载数据) 页面。

(1)上传数据文件

在 Web UI 上,你可以用文件的方式上传数据,前提是文件中的数据符合 InfluxDB 支持的类型,包括CSV、带Flux 注释的 CSV 和 InfluxDB 行协议。

MMSIZE

点击其中任意一个按钮,将进入数据的上传页面,页面中包含了详细的说明文档,包含你的数据应该符合什么格式,你要把数据放到哪个存储桶里,还包括用命令行来上传数据的命令模板。

MMSIZE

(2)写入 InfluxDB 的代码模板

InfluxDB 提供了各种编程语言的连接库,你甚至可以在前端嵌入向 InfluxDB 写入数据的代码,因为InfluxDB 向外提供了一套功能完整的REST API。

MMSIZE

点击任何一个语言的 LOGO,你会看到使用这门语言,将数据写入到 InfluxDB 的代码模板。

MMSIZE

建议从这里拷贝初始化客户端的代码。

配置Telegraf 的输入插件:

MMSIZE

Telegraf 是一个插件化的数据采集组件,在这里你可以找一下没有对应你的目标数据源的插件,点击它的 logo。可以看到这个插件配置的写法,但是关于这方面的内容,还是建议参考 Telegraf 的官方文档,那个更细更全一些。

MMSIZE

管理存储桶

你可以将 InfluxDB 中的 bucket 理解为普通关系型数据库中的 database。在 Load data 页面上,点击上访的BUCKETS 选项卡,就可以进入bucket 管理页面了。

MMSIZE

InfluxDB 是一个无模式的数据库,也就是除了在输入数据之前需要显示创建存储桶(数据库),你不需要手动创建 measurement 或者指定各个 field 都是什么类型,你甚至可以前后在同一个measurement 下插入 filed 不同的数据。

(1)创建 Bucket

点击右上角的 CREATE BUCKET 按钮,会有一个创建存储桶的弹窗,这里你可以给bucket 指定一个名称和数据的过期时间。比如,你设置过期时间为 6 小时,那 InfluxDB 就会自动把这个存储桶中距离当前时间超过 6 小时的数据删除。

在这里插入图片描述

(2)调整 Bucket 的设置

存储桶的过期时间的名称都是可以修改的,点击任一 Bucket 信息卡的 SETTINGS 按钮会弹出一个调整设置的会话框。

MMSIZE

重命名是 InfluxDB 不建议的操作,因为大量的代码和 InfluxDB 定时任务都需要通过指定 Bucket 的名称来进行连接,贸然更改 Bucket 的名称可能导致这些程序无法正常工作。

(3)设置 Label

在每个 Bucket 信息卡的左下方都有一个 Add a label 按钮,点击这个按钮,你可以为Bucket 添加一个标签。不过这个功能一般很少用

MMSIZE

(4)向 Bucket 添加数据

每个存储桶信息卡的右边都有一个添加数据按钮,点击这个按钮可以快速导入一些数据。这里还可以创建一个抓取任务(被抓取的数据在格式上必须符合 prometheus 数据格式)

示例 1:创建 Bucket 并从文件导入数据

(1)创建 Bucket

将鼠标悬停在☝️ 左侧的按钮上,点击 Buckets,进入 Bucketde 的管理页面。

MMSIZE

点击 CREATE BUCKET 按钮,指定一个名称,这里我们将其设为 example01, 删除策略保留默认的NEVER,表示永远不会删除数据

MMSIZE

点击CREATE 按钮,可以看到我们的Buckets 已经创建成功了。

(2)进入上传数据引导页面

在 Load Data 页面,点击 Line Prtocol 进入 InfluxDB 行协议格式数据的上传引导页面。

MMSIZE

(3)录入数据

MMSIZE

  1. 点击选择存储桶

  2. 选择ENTER MANUALLY,手动输入数据

  3. 将数据粘到输入框

  4. 在右侧指明时间精度,包括纳秒、微秒、毫秒和秒

数据如下:

people,name=tony age=12
people,name=xiaohong age=13
people,name=xiaobai age=14
people,name=xiaohei age=15
people,name=xiaohua age=12

当前我们写的数据格式叫做 InfluxDB 行协议。

最后点击 WRITE DATA,将数据写到 InfluxDB。如果出现 Data Written Successfully, 那么说明数据写入成功。

管理 Telegraf 数据源

点击 Load Data 页面的 TELEGRAF 选项卡,可以快速生成一些 Telegraf 配置文件。并向外暴露一个端口,允许 telegraf 远程使用 InfluxDB 中生成的配置。

MMSIZE

(1)什么是 Telegraf

Telegraf 是 InfluxDB 生态中的一个数据采集组件,它可以讲各种时序数据自动采集到InfluxDB。现在,Telegraf 不仅仅是 InfluxDB 的数据采集组件了,很多时序数据库都支持与 Telegraf 进行协作,不少类似的时序数据收集组件选择在 Telegraf 的基础上二次开发。

(2)创建 Telegraf 配置文件

InfluxDB 的 Web UI 为我们提供了几种最常用的 telegraf 配置模板,包括监控主机指标、云原生容器状态指标,nginx 和 redis 等。

MMSIZE

通过页面,你可以勾选几种监控目标,然后一步步操作去创建一个 Telegraf 的配置文出来。

(3)管理 Telegraf 配置文件接口

完成Telegraf 的配置后,页面上会多出一个关于 telegraf 实例的信息卡。如图所示:

MMSIZE

点击蓝色的 Setup Instructions。

MMSIZE

会弹出一个对话框,引导你完成 telegraf 的配置。可以看到第三步的命令。

telegraf --config http://localhost:8086/api/v2/telegrafs/09dc7d49c444f000

这个命令中有一个 URL,其实意思也就是 InluxDB 向外提供了一个 API,通过这个API 你可以访问到刚才生成的配置文件。

(4)修改 Telegraf 配置

已经生成的配置文件如何去修改呢?你可以点击卡片的标题。

MMSIZE

这个时候,会弹出一个配置文件的编辑页面,不过这个时候没有交互式的选项了,你需要自己直接面对配置文件。

MMSIZE

修改完配置文件后,记得点击右方的 SAVE CHANGES 保存修改。

示例 2:使用 Telegraf 将数据收集到 InfluxDB

在本示例中,我们会使用 Telegraf 这个工具将一台机器上的 CPU 使用情况转变成时序数据,写到我们的InfluxDB 中。

(1)下载 Telegraf

可以使用下面的命令下载 telegraf:

wget https://dl.influxdata.com/telegraf/releases/telegraf-1.23.4_linux_amd64.tar.gz

(2)解压压缩包

将 telegraf 解压到目标路径。

 tar -zxvf telegraf-1.23.4_linux_amd64.tar.gz -C /opt/module/

(3)创建一个新的 Bucket

创建一个名为 example02 的 buckets,因为是演示,所以可以将过期时间设为 1 小时。设置好后点击CREATE。

(4)在 Web UI 上创建 telegraf 配置文件

  1. 在左侧的工具栏上点击Telegraf 按钮。

  2. 点击右侧蓝色的 CREATE CONFIGURATION 创建 telegraf 配置文件

    MMSIZE

  3. 在 Bucket 栏选择 example02,表示让 telegraf 将抓取到的数据写到 example02 存储桶中,下面的选项卡勾选 System。点击 CONTINUE。

    MMSIZE

  4. 点击 CONTINUE 按钮后,会进入一个配置插件的页面。你可以自己决定是否启用这些插件。这里需要给生成的 Telegraf 配置起一个名字,方便管理。

    MMSIZE

  5. 点击 CREATE AND VERIFY 按钮,这个时候其实 Telegraf 的配置就已经创建好了,你会进入一个Telegraf 的配置引导界面,如图所示:

    MMSIZE

(5)声明 Telegraf 环境变量

按照 Web UI 上的建议,首先,你要在部署 Telegraf 的主机上声明一个环境变量叫INFLUX_TOKEN,它是用来赋予 Telegraf 向 InfluxDB 写数据权限的。这里我们就不配环境变量了,请在单一的shell 会话下完成后面的操作。

所以到你下载好 Telegraf 的机器上,执行下面的命令。(注意!TOKEN 是随机生成的, 请按照自己的情况修改命令)

export INFLUX_TOKEN=v4TsUzZWtqgot18kt_adS1r-7PTsMIQkbnhEQ7oqLCP2TQ5Q-PcUP6RMyTHLy4IryP1_2rIamNarsNqDc_S_eA==

(6)启动 Telegraf

首先 cd 到我们解压的 telegraf 目录。

cd /opt/module/telegraf-1.23.4

MMSIZE

telegraf 的可执行文件在 ./usr/bin 目录下。cd 过去。

 cd ./usr/bin

从 Web UI 中复制运行 telegraf 的命令,修改 host 然后执行,我的telegraf 和InfluxDB 在同一台机器上,所以可以使用 localhost。最终命令如下。

运行效果如下图所示。

MMSIZE

(7)验证数据采集结果

  1. 点击左侧按钮进入Data Explorer 页面。

  2. 在左下角第一个选项卡选择 example02,表示要从 example02 这个存储桶中查数据。

  3. 点击好第一个选项卡后,会自动弹出第二个选项卡,勾选 cpu。

  4. 点击右上方的 SUBMIT 按钮。

  5. 如果出现折线图,说明我们成功地使用Telegraf 把数据导进来了。

在这里插入图片描述

(8)编写启停脚本

后面我们很多时候都要使用 telegraf 抓取的主机监控数据来进行查询演示。为了方便启停,我们编写一个shell 脚本来管理 telegraf 任务。

  1. 首先 cd 到~/bin 路径下,如果~路径下没有 bin,就创建 bin 这个目录。通常,~/bin 是 PATH 环境变量包含的一个目录。

    cd ~
    mkdir bin
    cd ~/bin
    
  2. 到~/bin 路径下创建一个文件 host_tel.sh

     vim host_tel.sh
    
  3. 键入如下内容

    #!/bin/bash
    is_exist(){
        pid=`ps -ef | grep telegraf | grep -v grep | awk '{print $2}'`
        # 如果不存在返回 1,存在返回 0
        if [ -z "${pid}" ]; then
        	return 1
        else
        	return 0
        fi
    }
    stop(){
        is_exist
        if [ $? -eq "0" ]; then
        	kill ${pid}
        if [ $? -eq "0" ]; then
        	echo "进程号:${pid},弄死你"
        else
        	echo "进程号:${pid},没弄死"
        fi
        else
        	echo "本来没有 telegraf 进程"
        fi
    }
    start(){
        is_exist
        if [ $? -eq "0" ]; then
        	echo "跑着呢,pid 是${pid}"
        else
        	export INFLUX_TOKEN=v4TsUzZWtqgot18kt_adS1r-7PTsMIQkbnhEQ7oqLCP2TQ5Q-PcUP6RMyTHLy4IryP1_2rIamNarsNqDc_S_eA==
        /opt/module/telegraf-1.23.4/usr/bin/telegraf --config http://localhost:8086/api/v2/telegrafs/09dcf4afcfd90000
        fi
    }
    status(){
    	is_exist
        if [ $? -eq "0" ]; then
        	echo "telegraf 跑着呢"
        else
        	echo "telegraf 没有跑"
        fi
    }
    usage(){
        echo "哦!请你 start 或 stop 或 status"
        exit 1
    }
    case "$1" in
        "start")
        	start
       		;;
        "stop")
        	stop
        	;;
        "status")
        	status
        	;;
        *)
        	usage
        	;;
    esac 最后
    
  4. 最后给这个脚本加上一个执行权限,你可以执行下面的代码。

    chmod 755 ./host_tel.sh
    
    管理抓取任务

(1)什么是抓取任务

抓取任务就是你给定一个 URL,InfluxDB 每隔一段时间去访问这个链接,把访问到的数据入库。

在 InfluxDB 1.x 的时候,类似的任务只能由Telegraf 来实现。在 InfluxDB 2.x 中,内置了抓取功能(但是定制性上不如 Telegraf,比如轮询间隔只能是 10 秒)

MMSIZE

另外, 目标 URL 暴露出来的数据格式必须得是 Prometheus 数据格式。

(2)InfluxDB 自身暴露的监控接口

你可以访问 http://localhost:8086/metrics 来查看 InfluxDB 暴露出来的性能数据。这里面有,InfluxDB 的 GC 情况

MMSIZE

以及各个API 的使用情况,如图所示,说的是各个 API 被谁请求过多少次。

MMSIZE

示例 3:让 InfluxDB 主动拉取数据

(1)创建一个存储桶

创建了一个名为 example03 的存储桶。数据的过期时间设为 1 小时。

(2)创建抓取任务

  1. 进入抓取任务的管理页面

  2. 点击CREATE SCRAPER 按钮,创建抓取任务。

    MMSIZE

  3. 在对话框上,给抓取任务起一个名字,此处命名为 example03_scraper

  4. 右方的下拉框上,选择我们刚才创建的存储桶,example03。

  5. 最下方设置一下目标路径,最后点击 CREATE

    MMSIZE

  6. 如果页面上出现新的卡片,说明配置成功。接下来去看一下数据有没有进来。

    MMSIZE

(3)验证抓取结果

  1. 点击左侧的按钮,打开Data Explorer

  2. 在左下角第一个卡片选择要从哪个存储桶抽取数据,本例对应的是 example03

  3. 第一个卡片选择好后,会自动弹出第二个卡片,你可以选择任意一个指标名称。

  4. 点击右侧的 SUBMIT 按钮,提交查询。

  5. 如果折线图成功加载,说明有数据了,抓取成功!

MMSIZE

管理 API Token

点击左侧的 API Tokens 按钮,进入 API Token 的管理页面。

MMSIZE

(1)API Token 是干什么用的

简单来说,influxdb 会向外暴露一套 HTTP API。我们后面要学的命令行工具什么的, 其实都是封装的对 influxdb 的 http 请求。所以,在 InfluxDB 中,对权限的管理主要就体现在 API 的 Tokens 上。客户端会将 token 放到 http 的请求头上,influxdb 服务端就根据客户端发来的请求头部的 token,来判断你能不能对某个存储桶读写,能不能删除存储桶,创建仪表盘等。

(2)查看 API Token 权限

截至目前,我们还没有自己手动创建过 API Token。但是可以看到页面上已经有一些Token 了,这些 Token 是由我们之前示例里面的操作自动生成的。

MMSIZE

(3)了解 tony’s Token

现在,我们围绕着 InfluxDB 中已有的 Token 来学习相关的知识,我们的 InfluxDB 上现在只有初始化时创建的tony 账户,在 Token 列表中,我们可以看到有一个名为tony’s Token 的 token。

MMSIZE

  1. 修改 token 的名称

点击 token 右边的符号,可以修改token 名称。

  • 没有客户端会用 token 的名称来调用 token,所以修改 token 名称不会影响已经部署的应用。

  • InfluxDB 从未要求 token 的名称必须全局唯一,所以名称重复也是可以的。

  1. token 可以临时关停、也可以删除

    正如你说看到,token 卡片下面的 Active 按钮是一个开关,可以在启用和停用之间进行切换。

    同时,你也可以删除 token,但是这可能对你已经部署的应用产生不可挽回的影响。

  2. 查看 Token 权限

    点击 token 的名称,可以看到这个 token 具体有哪些权限。这里我们比较两个token,可以看到 tony’ Token 的权限很高。

    MMSIZE

    下面这个Token 是我们前面示例,生成Telegraf 配置的时候自动生成的 token。

    MMSIZE

    点开看一下它的权限。

    MMSIZE

    可以看到这个 token 的权限就小得多了,它只能向一个存储桶里写数据,查的权限都没有呢。

(4)创建 API Token

页面的右方有一个 GENERATE API TOKEN。点一下会出来一个下拉菜单,这其实是Web UI 上的权限模板

MMSIZE

在 Web UI 上,有两种类型的模板让你可以快速创建 token。

  • Read/Write API Token 仅读写存储桶的Token

    创建Token 时还可以限定这个Token 能操作哪些存储桶。

    MMSIZE

  • All Access API Token 生成带所有权限的Token

    MMSIZE

注意!InfluxDB 的 Token 是可以进行更细的管理的,Web UI 上给的只是生成 Token 的模板,准备了用户的常用需求,但不代表它的全部功能。

查询工具

S关于 InfluxDB 的查询,需要用户掌握一门叫 FLUX 的语言。本节暂时不讲解 FLUX 语言的知识,而是先了解InfluxDB 重要的两个开发工具——Data ExplorerNotebook

Data Explorer

explorer,探险家、探索者的意思。所以正如其字面意思,你可以使用Data Explorer 探索数据,理解数据。说白了,就是你可以尝试性地写写 FLUX 查询语言(InfluxDB 独创的一门独立查询语言),看一下数据的效果。开发过程中,你可以将它作为一个 FLUX 语言的 IDE。但是,目前我们不会向大家讲解 FLUX 语言。

点击左边的图标,进入Data Explorer。

我们可以将 Data Explorer 的界面简单分为两个区域,上半部分为数据预览区,下半部分为查询编辑区

MMSIZE

(1)查询编辑区

查询编辑区为你提供了两种查询工具,一个是查询构造器,一个是 FLUX 脚本编辑器。

1)查询构造器

你一进入 Data Explorer 页面,默认会打开查询构造器。使用查询构造器,你可以通过点按的方式完成查询。它背后的原理其实是根据你的设置,自动生成一条 FLUX 语句,提交给数据库完成查询。

能够出现查询构造器这种东西,说明时序数据的查询之间遵循着某种规律。不同业务之间的查询步骤可能高度相似。

MMSIZE

如上图,这是查询构造器的极简介绍。

2)FLUX 脚本编辑器

你可以手动将查询构造器切换为 FLUX 脚本编辑器。然后愉快地编写 FLUX 脚本,实现各种奇葩查询。编辑器十分友好,还带自动提示和函数文档。

MMSIZE

(2)数据预览区

数据预览区可以将你的数据展示出来。下图是一个效果图。

MMSIZE

默认情况下,数据预览区会将你的数据展示为一个折线图。不过除此之外,你还可以让数据展示为散点图、饼图或者查看原始数据等等。

(3)其他功能

除了查询和展示数据的功能外。Data Explorer 还有一些拓展功能

  1. 将数据导出为 CSV

在执行查询之后,DataExplorer 允许你快速地将数据导出为一个 CSV 文件。

MMSIZE

  1. 将当前查询和可视化效果保存为仪表盘的一个单元

你可以将当前的查询逻辑和图形展示保存为某个仪表盘的一部分。这个功能需要在查询逻辑已经实现的前提下,点击右上角的 SAVE AS 触达。

MMSIZE

  1. 创建定时任务

    MMSIZE

    Data Explorer 中的查询逻辑可以保存为一个定时任务,也就是 TASK。这里提前说一下 InfluxDB 中的 TASK 是什么。TASK 其实是一个定时执行的 FLUX 语言写的脚本。因为FLUX 是一个脚本语言,所以它其实有一定的 IO 能力。可以使用 http 与外面的系统进行通信,还可以将计算完的数据回写给 InfluxDB。所以通常TASK 有两种使用场景。

    • 数据检查与报警。对查询后的结果进行一下条件判断,如果不合规,就使用 http向外通知报警。
    • 聚合操作。在 InfluxDB 里开窗完成聚合计算,计算后的数据再写回到 InfluxDB, 这样下游 BI(数据看板)可以直接去查询聚合后的数据了,而不是每次都把数据从InfluxDB 里拉出来重新计算。这样可以减少 IO,不过会增加 InfluxDB 的压力。生产环境下需要根据实际情况进行取舍。

 

  1. 定义全局变量

    在 DataExplorer 里,你可以声明一些全局变量。全局变量的类型可以是 Map(键值对)、CSV 和 FLUX 脚本。这样,将来你可以直接引用这些变量,比如你的数据里有地区编码。你就可以将编码到地区名称的映射保存为一个全局Map,供以后每次查询时使用。

    MMSIZE

示例 4:在 Data Explorer 使用查询构造器进行查询和可视化

(1)打开 Data Explorer

点击左侧的按钮,进入Data Explorer 页面。

MMSIZE

(2)设置查询条件

我们现在要查询的是 test_init 存储桶下的 go_goroutines 测量,这个测量反应的是我们InfluxDB 进程中的 goroutines(轻量级线程)数量。

首先,在左下角的查询构造器的 FROM 选项卡,选择 test_init 存储桶

MMSIZE

接着会弹出一个 Filter 选项卡,默认情况下这里是选择_measurement,此处我们选择go_goroutines。

(3)注意查询时间范围

右上角有一个带时钟符号的下拉菜单,这个菜单可以帮你纵向选择要查询数据的时间范围,通常默认是 1h。如下图所示:

MMMSIZE

(4)注意右侧的窗口聚合选项

在查询构造器的最右边,有一个开窗聚合选项卡。使用查询构造器进行查询,就必须使用开窗聚合。默认情况下,DataExplorer 会根据你设置的查询时间范围,自动调整窗口大小,此处查询范围 1h 对应窗口大小 10s。

MMMSIZE

同时,聚合方式默认是平均值。

(5)提交查询

点击右侧的 SUBMIT 按钮可以立刻提交查询。之后,数据展示区会出现相应的折线图。如下图所示:

MMSIZE

点击View Raw Data,可以看到原始数据。

MMSIZE

(6)查询原理

我们使用查询构造器进行查询,其实是 Web UI 根据我们指定的查询条件生成了一套FLUX 查询脚本。点击SCRIPT EDITOR 按钮,可以看到查询构造器生成的 FLUX 脚本。

在这里插入图片描述

(7)可视化原理

其实默认情况下的可视化,是依据返回数据中的_value 来展示的,但是有些时候,你想查询的数据可能字段名不会被判别为_value。它会安静地躺在原始数据中。

MMSIZE

Notebook

Notebook 是 InfluxDB2.x 推出的功能,交互上模仿了 Jupyter NoteBook。它可以用于开发、文档编写、运行代码和展示结果。

你可以将 InfluxDB 笔记本视为按照顺序处理数据的集合。每个步骤都由一个“单元格” 表示。一个单元格可以执行查询、可视化、处理或将数据写入存储桶等操作。Notebook 可以帮你完成下述操作:

  • 执行 FLUX 代码、可视化数据和添加注释性的片段

  • 创建报警或者计划任务

  • 对数据进行降采样或者清洗

  • 生成要和团队分享的 Runbooks

  • 将数据回写到存储桶

Notebook 和 DataExplorer 相比,主要是交互风格上的不同。DataExplorer 倾向于一锤子买卖,而 Notebook 可以将数据展示拆分为一个又一个具体的步骤。另外,NoteBook 可以用来开发告警任务DataExplorer 则不能。

(1)进入 Notebook 的导航界面

点击左侧的按钮,即可进入 Notebook 的导航页面。

MMSIZE

导航页面分两个部分:

  • 上面是创建引导,除了创建一个空白的 Notebook,InfluxDB 还为你提供了 3 个模板。分别是 Set an Alert(设置一个报警)、Schedule a Task (调度一个任务)、write a Flux Script(写一个 Flux 脚本)。

  • 下面是 Notebook 列表,过去你创建过的NoteBook 再这里都会展示出来。

卡片上还有这个 Notebook 对应的创建时间和修改时间。通过卡片你可以对一个Notebook 重命名,还可以将它复制和删除。

(2)创建一个空白的 notebook

想要继续后面的步骤,我们必须先创建一个 Notebook。

现在,你看到的就是 Notebook 的操作页面了。

MMSIZE

(3)NoteBook 工作流

目前你看到的页面应当是如下图所示的样子。

MMSIZE

我们在页面中看到的一个又一个卡片,在 NoteBook 中叫做 Cell。一个 NoteBook 工作流就是多个 Cell 按照先后顺序组合起来的执行流程。这些 Cell 中间随时可以插入别的 Cell, 而且Cell 和Cell 还可以调换顺序。

按照Cell 功能,Cell 可以按照下面的方式分类。

MMSIZE

  • 数据源相关的Cell

    • 查询构造器

    • 直接编写 FLUX 脚本

  • 可视化相关的Cell

    • 将数据展示为一个Table

    • 将数据展示为一张图

    • 添加笔记。

  • 行为Cell

    • 进行报警

    • 定时任务设定

(4)工作流范式

在 NoteBook 里编写工作流通常是有套路可循的。

MMSIZE

通常一个 notebook 工作流以查询数据开始,后面的 Cell 跟上把数据展示出来,当数据需要进一步修改的时候,可以再加一个 FLUX 脚本 cell,notebook 为我们留了一个接口, 通过这种方式,后面的Flux cell 可以将前面的数据作为数据源进行查询。

最终,notebook 工作流可以以任务设置或者报警操作作为整个工作流的终点,当然这不是强制要求。

(5)NoteBook 控件

在 notebook 上存在下述几种控件

  1. 时区转换

    右上角有一个 Local 按钮,通过这个按钮,你可以选择将日期时间显示为系统所设时区还是 UTC 时间。

    MMMSIZE

  2. 仅显示可视化

    点击 Presentation 按钮,可以选择是否仅显示数据展示的 cell。如果开启这个选项,那么查询构造器和FLUX 脚本的Cell 就会被折叠。

  1. 删除按钮

    点击确定后,可以删除整个 notebook。

  2. 复制按钮

    右上角的复制按钮可以立刻为当前NoteBook 创建一个副本。

  3. 运行按钮

    RUN 按钮可以快速地执行Notebook 中的查询操作并重新渲染其中的可视化Cell。

示例 5:使用 NoteBook 查询和可视化数据

(1)使用查询构造器进行查询

默认情况下,你创建的空白 NoteBook,自带 3 个 cell。

MMSIZE

第一个 cell,默认是一个查询构造器,相对于 DataExplorer 来说,notebook 的查询构造器不同的地方在于它没有开窗聚合操作。

此处,同样还是查询 test_init 中的 go_goroutines 测量。

MMSIZE

(2)提交查询

点击RUN 按钮。

可以看到下面的原始数据和折线图都出现了:

MMSIZE

(3)添加说明 cell

notebook 允许用户在工作流中加入说明性的 cell。我们选择在最前面加一个说明性 cell。

首先,点击左侧的紫色+号。

MMSIZE

点击 NOTE 按钮。可以看到, 我们已经创建了一个说明 cell 。这里面还支持MarkDown 语法,

MMSIZE

点击右上右上角的PREVIEW 按钮,markdown 就会被渲染展示。

MMSIZE

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐