时序存储常见问题

已写入时序数据,使用PromQL为什么查不到数据?

首先确认下述两种场景是否存在问题。

  • 场景一:PromQL语法是否正确,时序库的查询框中会自动提示语法解析情况,若存在问题请按照提示修改;

    image

  • 场景二:参见下面的截图进入时序库的“自定义分析”页面,并执行下述的SQL确认对应时间段内有无数据。

    此SQL中的 __name__ 字段表示MetricName。

    * | select * from "MetricStore名字.prom" where __name__ = 'demo_api_request_duration_seconds_bucket'

    image.png

    image.png

上述两种场景检查没有问题,则可能是Prometheus计算引擎中的特殊的选点逻辑和lookback-delta”机制造成的。

Prometheus计算引擎提供了一种名为PromQL的查询语言,该语言在执行计算时不一定会将全部数据点都纳入计算点,在执行计算前实际还存在一个选点过程。PromQL语法所包含的所有算子、函数、运算符在数据选点这个流程上可分成两类:带“[1m]、[1h]”等操作符的RangeVectorSelectorInstantVectorSelector

下面分别列举了几项包含两种VectorSelector的PromQL示例。

RangeVectorSelector:
rate(http_requests_total[5m])
delta(http_requests_total[5m])
count_over_time(http_requests_total[5m])


InstantVector:
http_requests_total
absent(http_requests_total)
count(http_requests_total)

RangeVectorSelector的选点流程是将“[xx]”操作符所覆盖时间范围内的数据点都纳入计算,如下图,操作符“count_over_time ( up [30s] )”表示每次计算时都会将当前时间点及往前30秒的数据点都纳入到计算中。

image.png

PromQL中的“lookback-delta”机制仅对InstantVectorSelector有效,在“选点”时会根据“lookback-delta”参数值大小往前找特定时间区间,并将最近时间点的数据点作为当前时间点的数据值。在绝大多数情况下,原始数据的写入时间点和查询时间点是没有对齐的,在“选点”时会往前回溯n分钟(SLS默认3分钟,可通过自定义参数调整,请参见时序指标查询API),并将最近的数据点作为当前时间点的数据。

下图示例中,查询的startTime为09分28秒,该时间点不存在原始数据点,则会往前找到06分28秒,而这段时间都没有写入数据,则表示09分28秒没有选取到数据点。同理,09分43秒则选取了09分40秒的数据点、09分58秒选取了09分55秒的数据点。

image.png

由于该机制的特殊性,在“选点”时还存在一种特殊场景:在已经不存在数据的时间点,使用PromQL却查出了数据。下图示例中,10分00秒后已经不存在数据,但10分13秒、10分28秒、10分43秒、12分58秒等时间点都因为“lookback-delta”的机制往前回溯3分钟并选取到了10分00秒的数据点。

image.png

两类VectorSelector的“选点”逻辑是完全不一致的,而查不到数据通常也和这两类“选点”逻辑有关系,下面分别对两类逻辑查不到数据的可能性场景做分析。

  • RangeVectorSelector

    操作符“[xx]”中表示的时间区间较小,而运算的步长“step”参数较大,可能导致单次计算前的“选点”流程并没有选取到数据点。

    例如,原始写入的指标数据“up”为每小时(整点)一个点,查询参数为:

    startTime: 10:30:00
    endTime  : 18:30:00
    step     : 1h
    query    : count_over_time(up[10m])

    预期会返回7个数据点,而实际的查询结果为空,原因分析:PromQL计算逻辑会从startTime开始每间隔step执行一次计算,即在“11:30:00、12:30:00、13:30:00、14:30:00、15:30:00、16:30:00、17:30:00、18:30:00”这些时间点都会计算一次计算,但每次计算前的“选点”仅选取了近10分钟范围内所有点,致使每次“选点”都没有选到数据点。

  • InstantVectorSelector

    “lookback-delta”参数较小,而运算的步长“step”参数较大,可能导致单次计算前的“选点”流程没有找到最近的数据点。

    例如,原始写入的指标数据“up”为每小时(整点)一个点,查询参数为:

    startTime: 10:30:00
    endTime  : 18:30:00
    step     : 1h
    query    : count(up)

    Prometheus中默认的“lookback-delta”参数为5分钟,SLS时序库中默认为3分钟。在每次计算前的“选点”仅会往前找3分钟,即在“11:30:00、12:30:00、13:30:00、14:30:00、15:30:00、16:30:00、17:30:00、18:30:00”这些时间点都近会往前找3分钟,并将时间最近的数据点作为当前时刻的数据值。由于原始数据的分布较稀疏,上述几次“选点”都没有找到数据点,致使最后的计算结果同样为空。

解决方案

  1. 调整查询参数中的startTimeendTimestep参数,将参数与写入时间点对齐后,就能够选取到写入时间点的数据。

    例如,下面的查询会返回7个数据点。在实际的应用场景中,指标数据点采集时刻并不是非常规整的,并且查询时也并不会刻意去对齐参数,所以不推荐使用此方案。

    startTime: 10:00:00
    endTime  : 18:00:00
    step     : 1h
    query    : count(up)
  2. 调小step参数,例如我们将step参数设置为3分钟,以上述InstantVectorSelector场景为例,一定有多次“选点”能够选取原始的数据点。此方案是让“选取”流程变得更密集,以确保能够选取到原本较稀疏的数据点。

  3. 调大“lookback-delta”参数或者调大“[xx]”操作符的数值,调整此两项参数则是通过扩大“选点”的时间区间,将尽可能多的数据点纳入选择范围。

特定时间点之后已不再写入数据,为什么使用PromQL仍能查出在该时间点之后的数据?

原因同样与Prometheus计算引擎中的“lookback-delta”机制有关,请参见“lookback-delta”机制

单次Query计算资源超限,请求被拒绝

如果Query请求返回的错误中包含了“too many time Series or items,xxxxxx” 、“too many time Series or items in parallelMaster node,xxxxx”等文本提示,则说明该次Query读取了很大的数据量,已触发了计算层的内存限制。

image.png

解决方案

缩小查询区间。

vector cannot contain metrics with the same labelset错误

  • 原因一:__labels__字段值中的LabelName不符合字母序。

    写入MetricStore的__labels__字段由多组Label (LabelName#$#LabelValue)组成,且所有Label之间使用竖线(|)连接。在时序标识中,要求所有Label按照LabelName的字母序排序。更多信息,请参见时序标识

    __labels__字段值中的LabelName不符合字母序时,会出现该错误。您可以通过如下SQL语句确认__labels__字段值中的LabelName是否按照字母序排序。

    * | select * from (
    select __labels__, array_join(array_sort(split(__labels__, '|')), '|') as rightLabels from "MetricStore名字.prom" where __name__!=''
    ) where __labels__ != rightLabels
  • 原因二:__labels__字段值中存在LabelValue为空问题。

    在Prometheus Engine中,LabelValue为空的Label会被视作无效。Prometheus Engine执行计算时会删除无效Label,因此出现该错误。您可以通过下述步骤确认__labels__字段值中是否存在LabelValue为空问题。

    1. 缩小查询时间范围,定位到出现此错误的大致时间区间。

    2. 执行如下SQL语句。

      * | select __labels__ from "MetricStore名字.prom" where __name__!='' and regexp_like(__labels__, '.*#\$#\|.*|.*#\$#$')

      如果有返回结果,则表示存在LabelValue为空问题。建议修正数据上报端代码逻辑,删除无效Label。

PromQL查询时缺失Label信息,但原始数据中存在该Label

__labels__字段值中的LabelName未按照字母序排序时会出现该问题。您可以通过如下SQL语句确认__labels__字段值中的LabelName是否按照字母序排序。

* | select * from (
select __labels__, array_join(array_sort(split(__labels__, '|')), '|') as rightLabels from "MetricStore名字.prom" where __name__!=''
) where __labels__ != rightLabels

PromQL中涉及by/without计算时,结果不符合预期

__labels__字段值中的LabelName未按照字母序排序时会出现该问题。您可以通过如下SQL语句确认__labels__字段值中的LabelName是否按照字母序排序。

* | select * from (
select __labels__, array_join(array_sort(split(__labels__, '|')), '|') as rightLabels from "MetricStore名字.prom" where __name__!=''
) where __labels__ != rightLabels

指标探索中没有数据

可能原因是默认查询时间范围内没有数据。

在选择查询时间范围时,确保该时间范围内存在数据。

说明

使用指标探索功能时,为保证响应速度,系统默认查询范围为最近5分钟。

image.png

在控制台中,查询到的时序数据缺失较多时间线

在日志服务控制台的MetricStore查询分析页面中执行查询时,存在limit参数,该参数会限制SQL查询或PromQL查询的返回数据的数量。建议适当调大该参数。

image.png

PromQL计算结果中存在Warning信息

可能原因是在拉取原始数据时,因Shard读取能力上限问题,未将该时间段内的数据读取完整。建议缩小查询时间范围或者分裂Shard提升整体吞吐能力。

image.png

exceeded maximum resolution of 11,000 points per timeseries. Try decreasing the query resolution (?step=XX)错误

在Prometheus中,限制每条时间线最大存在11000个数据点,即 (endTime - startTime) / step的值最大为11000。建议缩小查询区间或者调大step参数。

image.png