如何使用 influxdb non_negative_derivative 获得一致的值?

Posted

技术标签:

【中文标题】如何使用 influxdb non_negative_derivative 获得一致的值?【英文标题】:How do I get consistent values with influxdb non_negative_derivative? 【发布时间】:2016-10-27 05:31:08 【问题描述】:

将 grafana 与 influxdb 一起使用,我试图显示作为计数器的某个值的每秒速率。如果我使用non_negative_derivative(1s) 函数,则速率的值似乎会根据 grafana 视图的时间宽度发生显着变化。我正在使用last 选择器(但也可以使用max,因为它是一个计数器,所以它的值相同)。

具体来说,我正在使用:

SELECT non_negative_derivative(last("my_counter"), 1s) FROM ...

根据influxdb docs non-negative-derivative:

InfluxDB 计算按时间顺序排列的字段值之间的差异,并将这些结果转换为每单位的变化率。

所以对我来说,这意味着在扩展时间视图时,给定点的值不应该有太大变化,因为该值应该是每单位的变化率(在我的示例查询中为 1s以上)。

在石墨中,它们具有特定的perSecond 功能,效果更好:

perSecond(consolidateBy(my_counter, 'max'))

关于我在上面的涌入查询中做错了什么有什么想法吗?

【问题讨论】:

【参考方案1】:

这里的问题是$__interval 宽度会根据您在 Grafana 中查看的时间范围而变化。

获得一致结果的方法是从每个区间(mean()median()max() 都同样有效)中抽取样本,然后通过derivative($__interval) 进行转换。这样,当您放大/缩小时,您的导数会发生变化以匹配您的区间长度。

因此,您的查询可能如下所示:

SELECT derivative(mean("mem.gc.count"), $__interval) FROM "influxdb"
WHERE $timeFilter GROUP BY time($__interval) fill(null)

【讨论】:

【参考方案2】:

@Michael-Desa 给出了很好的解释。

我想通过针对我们公司感兴趣的一个非常常见的指标的解决方案来扩充这个答案:“特定测量字段上的最大“每秒操作”值是多少? .

我将使用我们公司的真实示例。

场景背景

我们将大量数据从 RDBMS 发送到 redis。在传输该数据时,我们会跟踪 5 个计数器:

    TipTrgUp -> 由业务触发器更新(存储过程) TipTrgRm -> 由业务触发器删除(存储过程) TipRprUp -> 通过无人值守的自动修复批处理更新 TipRprRm -> 通过无人值守的自动修复批处理删除 TipDmpUp -> 由批量转储进程更新

我们制作了一个指标收集器,将这些计数器的当前状态发送到 InfluxDB,间隔为 1 秒(可配置)。

Grafana 图 1:低分辨率,没有真正的最大操作数

这是有用的 grafana 查询,但在缩小时不显示真正的最大操作数(我们知道在正常工作日,当没有特殊转储或维护发生时,它会达到大约 500 个操作数 - 否则它进入数千个):

SELECT
    non_negative_derivative(max(TipTrgUp),1s) AS "update/TipTrgUp"
   ,non_negative_derivative(max(TipTrgRm),1s) AS "remove/TipTrgRm"
   ,non_negative_derivative(max(TipRprUp),1s) AS "autorepair-up/TipRprUp"
   ,non_negative_derivative(max(TipRprRm),1s) AS "autorepair-rm/TipRprRm"
   ,non_negative_derivative(max(TipDmpUp),1s) AS "dump/TipDmpUp"
FROM "$rp"."redis_flux_-transid-d-s"
WHERE
    host =~ /$server$/
    AND $timeFilter
GROUP BY time($interval),* fill(null)

旁注:$rp 是保留策略的名称,以 grafana 为模板。我们使用 CQ 对具有更长持续时间的保留策略进行下采样。另请注意1s 作为派生参数:它是必需的,因为使用 GROUP BY 时默认值不同。这在 InfluxDB 文档中很容易被忽略。

24 小时查看的图表如下所示:

如果我们简单地使用 1s 的分辨率(正如@Michael-Desa 所建议的那样),大量数据将从 influxdb 传输到客户端。它运行得相当好(大约 10 秒),但对我们来说太慢了。

Grafana 图 2:低分辨率和高分辨率,真正的最大操作数,性能缓慢

但是,我们可以使用 子查询 将真正的 maxops 添加到该图中,这是一个轻微的改进。传输到客户端的数据要少得多,但 InfluxDB 服务器必须进行大量的数字运算。系列 B(在别名前加上maxops):

SELECT
    max(subTipTrgUp) AS maxopsTipTrgUp
   ,max(subTipTrgRm) AS maxopsTipTrgRm
   ,max(subTipRprUp) AS maxopsRprUp
   ,max(subTipRprRm) AS maxopsTipRprRm
   ,max(subTipDmpUp) AS maxopsTipDmpUp
FROM (
    SELECT
        non_negative_derivative(max(TipTrgUp),1s) AS subTipTrgUp
       ,non_negative_derivative(max(TipTrgRm),1s) AS subTipTrgRm
       ,non_negative_derivative(max(TipRprUp),1s) AS subTipRprUp
       ,non_negative_derivative(max(TipRprRm),1s) AS subTipRprRm
       ,non_negative_derivative(max(TipDmpUp),1s) AS subTipDmpUp
    FROM "$rp"."redis_flux_-transid-d-s"
    WHERE
        host =~ /$server$/
        AND $timeFilter
    GROUP BY time(1s),* fill(null)
)
WHERE $timeFilter
GROUP BY time($interval),* fill(null)

提供:

Grafana 图 3:低分辨率和高分辨率、真正的最大操作数、高性能、由 CQ 预先计算

我们对这类指标的最终解决方案(但仅当我们需要实时视图时,子查询方法才适用于 ad-hoc 图)是:使用连续查询来预先计算真正的 maxops。我们像这样生成 CQ:

CREATE CONTINUOUS QUERY "redis_flux_-transid-d-s.maxops.1s"
ON telegraf
BEGIN
    SELECT
        non_negative_derivative(max(TipTrgUp),1s) AS TipTrgUp
       ,non_negative_derivative(max(TipTrgRm),1s) AS TipTrgRm
       ,non_negative_derivative(max(TipRprUp),1s) AS TipRprUp
       ,non_negative_derivative(max(TipRprRm),1s) AS TipRprRm
       ,non_negative_derivative(max(TipDmpUp),1s) AS TipDmpUp
    INTO telegraf.A."redis_flux_-transid-d-s.maxops"
    FROM telegraf.A."redis_flux_-transid-d-s"
    GROUP BY time(1s),*
END

从这里开始,在 grafana 中使用这些 maxops 测量是微不足道的。当下采样到保留时间更长的 RP 时,我们再次使用 max() 作为选择器函数。

B 系列(别名中附加.maxops

SELECT
    max(TipTrgUp) AS "update/TipTrgUp.maxops"
   ,max(TipTrgRm) AS "remove/TipTrgRm.maxops"
   ,max(TipRprUp) as "autorepair-up/TipRprUp.maxops"
   ,max(TipRprRm) as "autorepair-rm/TipRprRm.maxops"
   ,max(TipDmpUp) as "dump/TipDmpUp.maxops"
FROM "$rp"."redis_flux_-transid-d-s.maxops"
WHERE
    host =~ /$server$/
    AND $timeFilter
GROUP BY time($interval),* fill(null)

提供:

当放大到 1s 精度时,您可以看到图形变得相同:

希望这有帮助,TW

【讨论】:

【参考方案3】:

如果您想要每秒不变的结果,您需要GROUP BY time(1s)。这将为您提供准确的perSecond 结果。

考虑以下示例:

假设计数器的值每秒都在变化

0s → 1s → 2s → 3s → 4s
1  → 2  → 5  → 8  → 11

根据我们对上述序列的分组方式,我们会看到不同的结果。

考虑我们将事物分组到 2s 存储桶中的情况。

 0s-2s   →    2s-4s
(5-1)/2  →  (11-5)/2
   2     →      3

相对于1s 存储桶

 0s-1s  →  1s-2s  →  2s-3s  →  3s-4s
(2-1)/1 → (5-2)/1 → (8-5)/1 → (11-8)/1
   1    →    3    →    3    →    3

寻址

所以对我来说,这意味着在扩展时间视图时,给定点的值不应该有太大变化,因为该值应该是每单位的变化率(在上面的示例查询中为 1s)。

rate of change per unit 是一个标准化因子,与 GROUP BY 时间单位无关。当我们将导数区间更改为2s 时,解释我们之前的示例可能会提供一些见解。

确切的方程式是

∆y/(∆x/tu)

考虑我们将事物分组到具有2s 导数区间的1s 桶的情况。我们应该看到的结果是

 0s-1s    →  1s-2s    →  2s-3s    →  3s-4s
2*(2-1)/1 → 2*(5-2)/1 → 2*(8-5)/1 → (11-8)/1
   2      →    6      →    6      →    6

这可能看起来有点奇怪,但如果你考虑一下它所说的应该是有道理的。当我们指定2s 的导数区间时,我们要求的是2s 变化率对于1s GROUP BY 桶的变化率。

如果我们对具有2s 的导数区间的2s 桶的情况应用类似的推理,那么

 0s-2s     →    2s-4s
2*(5-1)/2  →  2*(11-5)/2
   4       →      6

我们在这里要求的是2s 变化率是2s GROUP BY 存储桶的变化率,在第一个间隔中,2s 变化率将是4,第二个间隔2s 的变化率将是 6

【讨论】:

作为后续,对于您的解决方案,在执行 group by time (1s) 时,应该在 non_negative_derivative 中指定内部,对吗?所以:non_negative_derivative(last("EnqueueCount")) AS "EnqueueRate" ... group by (1s)

以上是关于如何使用 influxdb non_negative_derivative 获得一致的值?的主要内容,如果未能解决你的问题,请参考以下文章

influxDB:如何在 influxDB v2.0 中将字段转换为标签

如何使用 SpringBoot 2、InfluxDB 和 Grafana 理解微米指标?

如何在 grafana 图例中使用 InfluxDB-tag 值?

如何使用 libcurl(对于 Influxdb)发布包含换行符的数据?

如何看待influxdb集群功能不再开源

如何使用 python 客户端将大量行从 InfluxDB 导出到 CSV?