文章目录
参考官方文档 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个标签HttpMethod
和success
,有4个标签值GET,POST
和true,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推荐使用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