InfluxDB数据建模和最佳实践

参考官方文档 1.8 版本

指标分为事件指标聚合指标

  • 事件指标常用于关键事件的告警和索引故障排查用。
  • 聚合指标常用于统计数据和趋势分析用。

事件指标

基于事件的指标会在事件发生时立即发布。例如:当用户登录失败时,要立即发送事件告警。

示例

name: event.error
fields:
  # 用于跟ELK关联款速索引查询
  trackingId: "trackingId"
  # 耗时单位ms
  duration: 10000
  description: "描述"
  userId: "用户id"
  orgId: "组织id"
  success: 成功 失败
  status: 状态
tag:
    module: "login"
    region: "hefei"
    service: "CI"
    instanceindex: "机器的索引 1,2,3"

聚合指标

聚合指标会汇总数据按时间间隔发布,在客户端收集、汇总然后发出指标。例如,如果在 30 秒的窗口期间,给定的 HTTP 端点接收到 10,000 个 API 调用,而不是发出 10,000 个指标,则聚合指标将发出 1 个具有 4 个字段的指标。这将节省 9999 个指标。

示例

// timer类型
name: http.request
fields:
  # 在报告间隔内所有数据点的 毫秒平均值
  mean: 100
  # 在报告期间看到的 记录总数
  count: 1000
  # 在报告间隔内看到的 所有记录的毫秒和
  sum: 10000
  # 在该间隔内看到的 最大时间
  upper: 250
tag:
    region: "hefei"
    service: "CI"
    instanceindex: "机器的索引 1,2,3"

对比分析

事件指标和聚合指标的优缺点

事件指标

优点

  • 能附加更多的字段。
  • 能更实时的发送。
  • 能进行更多维度的统计,因为原始数据粒度更细。

缺点

  • 指标记录数太大了。

聚合指标

优点

  • 指标的记录数大大降低。例如,一天的事件指标数原来为100W,假设1分钟聚合一次,聚合后的指标为每分钟一条 * tag * tagvalue = 1440 * 系列基数。
  • 也大大降低指标写入频率。
  • 可以提前预估数据规模问题。

缺点

  • 无法添加其他附件字段。
  • 注意客户端基数爆炸问题,因为是在每个客户端内存统计,基数过大会导致内存溢出。
  • 无法做更多维度的统计,因为原始数据已经在客户端处理了一轮,粒度变粗了。

举例分析事件指标和聚合指标记录数的差异

如果有n个事件,其有m个具有k个不同标签值的标签,则生成的记录数为:

  • 事件指标n个记录
  • 聚合指标时间间隔 * m * k个记录

假设一天有 10w个 http 请求,请求实体有2个标签HttpMethodsuccess,有4个标签值GET,POSTtrue,false

n = 10W
m = 2, k = 4

则一天有
事件指标 = 10w points
聚合指标 = 1440 * 2 * 4 = 11520 = 1w多 (1天有1440分钟,聚合步长为1分钟)

客户端和服务端基数计算

name: laker
tags:
    module: "login"           # 一个客户端内存可能3个值 服务端:3个值    
        - login
        - user
        - order
    region: "hefei"          #  一个客户端内存只可能1个 服务端:2个值
         - hefei
         - hangzhou
    service: "CI"            #  一个客户端内存只可能1个 服务端:20个值 假设20个服务
    instanceindex: "1"       #  一个客户端内存只可能1个 服务端:3 
         - 1
         - 2
         - 3

基数只跟tag数和tagvalue数量有关

客户端内存基数: 3 * 1 * 1 * 1 = 3

服务端基数: 3* 2* 20 * 3 = 360

最佳实践

事件指标和聚合指标的选择问题

以下情况可以选择事件指标

  • 事件的确切时间是必要的并且频率低。
  • 需要通过事件实时告警的。
  • 需要添加较多指端排查问题的。
  • 高基数事件UserIds 需要与指标一起发出。注意后端数据存储的基数。

注意所有搞不定的都建议通过日志记录或其他后端来完成,毕竟都是在日志系统上做的升华。

Field和Tag的选择问题

  • 标签Tag不要在标签值中使用高基数项,不要使用 UserId、OrgId、ClientIds、TrackingIds 等(建议放在Field)因为这些数据都是存储在内存里,会导致OOM。

  • 对于influxdb而言,不支持根据field进行分组。特别强调,用来分组的必须是tag

  • 把你经常查询的字段作为tag。

  • 如果你要对其使用GROUP BY(),也要放在tag中。

  • 如果你要对其使用InfluxQL函数,则将其放到field中。

  • 如果你需要存储的值不是字符串,则需要放到field中,因为tag value只能是字符串。

  • tag的名字和值不要太长,名字和值的长度越长,占用的内存越多。

  • 数值的规模很大,那就是field

  • 如果要作为where的条件,那应该作为tag。 field可以作为条件,但是效率很差。

  • 如果要作为group by的条件,那需要作为tag, field不能进行group by。

  • 如果需要做数学运算(如mean, percentile, stddev), 那必须是field。 tag的值不能进行数学运算。

  • 如果需要存储数据的类型(int, float, string, boolean), 必须是filed. tag只能是字符串。

  • tag内存中有索引,field没有索引

  • 不要在一个tag里存储多个信息。

其他问题

  • 一个Point由measurement名称,tag set和timestamp唯一标识。如果提交具有相同measurement,tag set和timestamp,但具有不同field set的行协议,则field set将变为旧field set与新field set的合并,并且如果有任何冲突以新field set为准。

  • 注意tag的设计,因为主键是由time + tag组成,是不可以重复的,如果重复,后面的将覆盖前面的。

    • 增加新的tag来标识不同的点(例如:多加个tag - instanceid)
    • 或者用不同的tag value区分记录
  • 避免在influxdb中使用大量的字段,限制每张表中的字段数量,最好保持在一百个以内;

  • 不可以更新和重命名tag

  • 时间戳 建议使用最粗糙的精度,因为这样可以显着提高压缩率。 Influxdb并不要求时间戳唯一,不同的tag, 相同的时间戳可以写入一条新的记录。也就是说对于普通的采集,以毫秒为单位完全可以满足需求。

  • 批量写入 建议每批写1000 point开始, 然后根据机器配置和应用调整。

数据保留策略和连续查询

InfluxDB 每秒可以处理数十万个数据点。长时间处理如此多的数据可能会产生存储问题查询性能问题

一个通用的解决方案是对数据进行下采样进行数据冷热分离;仅在有限的时间内保留高精度的原始数据,而将较低精度的汇总数据存储更长时间或永久存储。

InfluxDB 提供了两个功能 - 连续查询 (CQ) 和保留策略 (RP) - 可自动执行下采样数据和使旧数据过期的过程。

大批量的热数据强烈建议保存24H,7d等。通过连续查询 (CQ) 和保留策略 (RP) - 可自动执行下采样数据和使旧数据过期的过程。

1.一个数据库可以有多个 RP,每个数据库的 RP 都是唯一的,建立2个保留策略,7d和1y。

2.指标直接写入7d的保留策略。

3.增加CQ从7d的保留策略下采样到1y的保留策略。

详情和具体步骤参见InfluxDB连续查询(通过下采样聚合原始数据降低数据样本数)和数据保留策略(过期删除)

建模示例

influxdb推荐使用tag,而不是创建很多measurement

但是最终的选择还是要结合自己的业务场景

:我有10万个设备要上传数据,使用10万个measurement存储,还是一个measurement加上不同的tag存储

:这个问题很大程度上取决于您的数据结构和使用方式。如果您的数据结构是相同的,那么使用一个measurement加上不同的tag存储比较优化,但如果您的数据字段和数据类型不同,那么使用10万个measurement存储可能更加合理。

原始数据结构

采集时间 设备ID 数据源 数据 类型
2018-11-15T05:40:46.3592112Z CNC001 温度 10.5 float
2018-11-15T05:41:41.9896781Z CNC001 设备状态 run String
2018-11-15T05:42:02.8402281Z CNC001 湿度 10 int
2018-11-15T05:42:02.8402281Z CNC002 温度 -1.2 float
2018-11-15T05:42:04.8402281Z CNC002 设备状态 run String

measurement

可以有以下3种选择

  • 只有一个measurement存放所有数据。

  • 1个设备作为1个measurement,用于存放一个设备的所有测量指标。

  • 选择数据源作为measurement。

tag

方便根据数据源进行查询,聚合,group等操作。根据实际业务场景决定,例如你想绘制哪些图表,需要什么SQL支持,需要哪些Group By 和 where过滤。

只有tag才支持Group By

值太多的强烈建议放在field中

timestamp

采集时间作为timestamp, 单位ms。

方案一

只有一个measurement

业务字段 influxdb类型
采集时间 timestamp
设备ID tag
数据源 tag
采集数据 field value
数据类型 field value
入库时间 field value

方案二

每类指标一个measurement

measurement: 温度

业务字段 influxdb类型
采集时间 timestamp
设备ID tag
采集数据 field value
数据类型 field value
入库时间 field value

measurement: 设备状态

业务字段 influxdb类型
采集时间 timestamp
设备ID tag
采集数据 field value
数据类型 field value
入库时间 field value

measurement: 湿度

业务字段 influxdb类型
采集时间 timestamp
设备ID tag
采集数据 field value
数据类型 field value
入库时间 field value

方案三

每个设备一个measurement

measurement: xxx-CNC001

业务字段 influxdb类型
采集时间 timestamp
数据源 tag
采集数据 field value
数据类型 field value
入库时间 field value

measurement: xxx-CNC002

业务字段 influxdb类型
采集时间 timestamp
数据源 tag
采集数据 field value
数据类型 field value
入库时间 field value

参考

  • https://unanao.github.io/2018/04/11/tsdb-influxdb/

  • https://docs.influxdata.com/influxdb/v1.8/concepts/schema_and_data_layout/

  • https://help.aliyun.com/document_detail/113127.html

猜你喜欢

转载自blog.csdn.net/abu935009066/article/details/129309177