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

问题描述 投票:10回答:3

使用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'))

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

influxdb grafana
3个回答
18
投票

如果你想要每秒的结果不变,你会想要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)

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

 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


6
投票

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

我想通过解决我们公司感兴趣的一个非常常见的指标来增加答案:“特定测量领域的每秒最大操作值”是多少?

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

场景背景

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

  1. TipTrgUp - >业务触发更新(存储过程)
  2. TipTrgRm - >通过业务触发器(存储过程)删除
  3. TipRprUp - >通过无人值守的自动修复批处理进行更新
  4. TipRprRm - >通过无人参与的自动修复批处理删除
  5. 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是保留政策的名称,用格拉法纳模板化。我们使用CQ来缩减采样到具有更长持续时间的保留策略。另请注意1s作为派生参数:它是必需的,因为使用GROUP BY时默认值不同。在InfluxDB文档中很容易忽略这一点。

24小时看到的图表看起来像这样:enter image description here

如果我们只使用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)

给:enter image description here

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)

给:enter image description here

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

希望这会有所帮助,TW


0
投票

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

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

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

SELECT derivative(mean("mem.gc.count"), $__interval) FROM "influxdb"
WHERE $timeFilter GROUP BY time($__interval) fill(null)
© www.soinside.com 2019 - 2024. All rights reserved.