You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Prometheus rate函数在序列正常时返回异常高值?

问题描述

我有一个计数器序列,直接查询时显示正常:

energy_watthours_total{meter="export"}

响应数据(核心片段):

{"status":"success",
 "data":
    {"resultType":"matrix",
     "result":
        [{"metric": {"__name__":"energy_watthours_total","instance":"XXX","job":"XXX","meter":"export"},
          "values": [
            [1728564000,"24335660"],
            [1728564014,"24335660"],
            [1728564028,"24335736"],
            [1728564042,"24335730"], // 此处数值较前一个点下降
            [1728564056,"24335798"],
            ...
          ]
        }]
    }
}

但查询其速率时,偶尔会得到异常高的值:

rate(energy_watthours_total{meter="export"}[1m])

响应中出现异常值(核心片段):

{"status":"success",
 "data":
    {"resultType":"matrix",
     "result":
        [{"metric": {"instance":"XXX","job":"XXX","meter":"export"},
          "values":[
             [1728564000,"3.822222222222222"],
             [1728564014,"3.822222222222222"],
             [1728564028,"4.266666666666666"],
             [1728564042,"540796.8666666666"], // 异常高值
             [1728564056,"540797.2"], // 后续点受连锁影响
             ...
          ]
      }]
   }
} 

TSDB dump确认存在计数器数值下降的情况:

$ promtool tsdb dump --min-time=1728564000000 --max-time=1728564196000 --match='energy_watthours_total{meter="export"}'
{__name__="energy_watthours_total", instance="XXX", job="XXX", meter="export"} 2.4335736e+07 1728564014395
{__name__="energy_watthours_total", instance="XXX", job="XXX", meter="export"} 2.433573e+07 1728564029395 // 数值从24335736降到24335730
...

该问题影响rate、irate和increase,但不影响delta;推测与计数器重置检测有关,想知道具体原因及解决方法?

原因分析

这确实是Prometheus计数器重置检测逻辑导致的问题:

  1. 计数器非预期下降:你的计数器在某个时间点出现了数值减少,这违反了计数器单调递增的规则(正常情况下计数器只会上升,仅在设备重启等场景下才会归零重置)。
  2. Prometheus重置处理逻辑:rate/irate/increase函数默认会检测计数器重置:当发现后一个样本值小于前一个样本值时,会判定计数器已重置为0并重新计数。此时计算差值时,会自动加上**无符号64位整数的最大值(2^64-1)**到当前样本值,再减去前一个样本值,导致差值异常巨大,最终计算出的速率飙升。
  3. delta不受影响的原因:delta函数仅计算样本的原始差值,不会处理计数器重置,所以即使数值下降,也只会得到负数差值,不会出现异常高值。
解决方法

1. 根源修复:解决计数器数值下降问题

这是最彻底的方案,需要排查数据源:

  • 检查设备固件是否存在bug,导致计数器偶尔回滚;
  • 排查数据采集逻辑,确认是否存在重复上报、数值计算错误的情况;
  • 确保计数器严格遵循单调递增规则,仅在设备重启等真正重置场景下归零。

2. 规避重置检测:修改PromQL查询

如果暂时无法修复数据源,可以通过修改查询逻辑跳过假重置的影响:

方案A:用delta手动计算速率并过滤负数

max(delta(energy_watthours_total{meter="export"}[1m]), 0) / 60
  • 原理:delta计算原始差值,max(..., 0)将负数差值(假重置或真重置)转为0,再除以时间范围(60秒)得到速率;
  • 优点:避免假重置导致的异常高值,同时处理真重置的情况;
  • 缺点:无法利用rate/irate的平滑逻辑,适合短时间范围查询。

方案B:排除触发重置检测的样本

rate(energy_watthours_total{meter="export"}[1m])
unless
(energy_watthours_total{meter="export"} - last_over_time(energy_watthours_total{meter="export"}[1m])) < 0
  • 原理:判断当前样本是否比1分钟内的最后一个样本小,若是则排除该点的速率值;
  • 优点:保留rate的平滑特性,仅过滤异常点;
  • 缺点:会丢失触发条件的样本数据,若存在真重置场景需要额外处理。

方案C:使用resets函数标记重置

rate(energy_watthours_total{meter="export"}[1m])
unless
resets(energy_watthours_total{meter="export"}[1m]) > 0
  • 原理:resets函数统计指定时间范围内的重置次数,若次数大于0则排除该点的速率值;
  • 优点:精准过滤触发重置检测的点;
  • 缺点:同样会丢失重置点的数据,需结合业务场景判断是否接受。

内容的提问来源于stack exchange,提问作者b0fh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:28:11