Influxdb2.x版本的学习

1,066 阅读5分钟

因为最近在做关于监控相关工作,在使用时序数据库存储监控数据时(neflow, telemery),选择了influxdb2.x版本,下面简单说下influxdb2.x的特点,以及适配于新版的flux语法

系统常用名词概念

  • organization:这是一个2.x版本新增的名词,表示工作区概念,服务目标是一组用户群体。influxdb的每一bucket、dashboard,、taskmember等都必须从属于一个organization
  • bucket:bucket是用来存放每一条时序数据记录的最终位置,每个bucket都可以设定其存放的时序数据保留周期,即最大保留时间点1 influxdb里面的每一条记录,可以称为point,每一条point包含如下信息
  • measurement:类似于关系型数据库里表名的概念
  • tag:每一个tag有key和value2个字段,都必须是字符串类型,针对tag字段,更多是用来做查询条件用,例如需要group条件之类的情况,但如果tag的value会随着时间不断变化或者很多,建议更换为field字段
  • field:同tag,每一个field也有key和value2个字段,其中只有key字段必须是字符串类型,value字段用来存储值。注意不要使用field作为查询条件,因为influxdb使用field字段的值做查询条件会扫描所有相关field。
  • timstamp:Unix时间戳,可以精细到纳秒级别 以go为例,写一条point记录到influxdb,可以清晰的看到每一个系统名词的意义 image.png

Influxdb Storage Engine 这里简单介绍一下influxdb的数据引擎,可以增加我们进行数据结构设计时的理解 存储引擎主要包含下面几个组件

  • WAL(Write Ahead Log)

    如果要理解WAL,那我们就需要明白数据是如何写入到influxdb里的。首先,每一个时间点的数据需要按照Line Protocol格式在终端通过http协议传入,这些时间点数据会分批的送往influxdb,进行压缩,然后生成一个WAL,同时,时间点数据也会被写入到内存变为立即可查询状态,内存中的数据会定期的按照TSM的格式写入到磁盘里,随着TSM文件时间点的积累增多,存储引擎将会将TSM文件合并为更高级别的TSM文件

    WAL的作用即使为了确保在发生不可预期的错误时,确保数据的完整性,下面是数据引擎是如何将数据详细写入到磁盘里的

    1. 在生成WAL后,会有一个写入的请求在WAL文件的末尾
    2. 数据通过fsync()函数写入
    3. 内存里数据进行更新
    4. 当成功将数据写入到磁盘后,有一个确认写入成功的响应

    *fsync() *: fsync函数是发生在系统级别的调用,它有一个内核上下文切换,需要比较大的数据量,但是上下文保证了数据的安全性

    Line Protocol: line protocol实际上是一个文本数据的格式化

    // Syntax
    <measurement>[,<tag_key>=<tag_value>[,<tag_key>=<tag_value>]] <field_key>=<field_value>[,<field_key>=<field_value>] [<timestamp>]
    ​
    // Example
    myMeasurement,tag1=value1,tag2=value2 fieldKey="fieldValue" 1556813561098000000
    

    虽然每个时间点数据都可以立即被发送到写入请求,但是为了效率,在做程序设计时应注意将时间点数据分批进行写入

  • Cache

    通过上面对WAL的讲解,可以知道,缓存时对存放在WAL里面的数据的一个数据副本,二者相互独立

    缓存的特点:

    • 根据时间点数据的key(measurement, tag set, and unique field),每一个field的值字段都存储在自己的时间范围内
    • 存放的时未压缩的数据
    • 每一次数据引擎重启都会重新从WAL文件获取更新,查询时会于TSM文件进行合并
    • 使用内存的最大值
  • TSM(Time-Structed Merge Tree)

    为了有效地压缩和存储数据,存储引擎按series key对field值进行分组,然后按时间对这些值进行排序。一个series key由mesurement, tag key and value, field value决定

    TSM 文件以柱状格式存储压缩的序列数据。为了提高效率,存储引擎只存储序列中值之间的差异(或增量)。面向列的存储允许引擎通过系列键读取并省略无关数据

    在数据成功的被存入的TSM文件后,将截断 WAL 并清除缓存

  • TSI(Time Series Index)

    官方文档只是简单说了下随着数据的series 的增多,那么查询就会越慢。根据官方文档,TSI存储了所有的series key

常用的flux语法

这里我以交换机设备的流量为例进行示范

简单的tag和field查询:下面是原始的数据表结构, 有2个tagSet 分别是Device和Port, 以及2个fieldSet SendBits和ReceiveBits, measurement以及时间戳序列

image-20220725155838473.png image-20220725160210114.png

  • 查询fields

    可以看到,根据不同series key,将field的值数据按照时间序列存储在自己的时间范围内 image-20220725160816097.png

  • 查询tag

    增加了tag字段,结果如下 image-20220725161221134.png

  • 使用derivative函数对查询到的field值做处理 image-20220725162346762.png

上面我们可以看到,每一次新增新的函数如filter以及derivative都会对原有的查询结果进行处理,因此要特别注意函数之间的执行顺序,接下来我们看另外个查询,我这边以netflow的流量记录为例,数据结构中除了netflow来源设备Agent以及BgpNextHop作为tag字段,其余源IP,目的IP,源端口等都作为fields字段,这里是考虑到这些字段的值太多会引起series key的成倍增长导致查询速度过慢才如此设计

  • 简单查询 image-20220725163509927.png

  • 统计BgpNextHop的出口流量: 这里使用group函数将BgpNextHop tag字段作为条件以及aggregateWindow函数对数据进行处理

image.png

  • 统计最大的10个源IP流量: 因为SrcIP和Bit都是field字段,注意都先要全部查出来,然后使用pivot函数进行反转,并使用group将srcIP作为条件,去处理数据,最后使用highestMax函数得到最大的几个值结果 image-20220725164357246.png

后续还有多表数据聚合,涉及到多表的联合查询,不过这里个人没有相关实例就略过了