オブザーバブル|Prometheusプラクティスレビューでの時系列データのダウンサンプリング

著者:Zhizhen

Prometheusに基づく監視の実践では、特に規模が大きい場合、時系列データの保存とクエリは非常に重要で問題のある部分です。大量のデータの下で長期的なクエリを処理する方法については、ネイティブのPrometheusシステムでは満足のいく答えが得られていません。この点で、ARMS Prometheusは最近ダウンサンプリング機能を開始し、この問題を解決するための新たな試みを行いました。

序文

問題の背景

PrometheusとK8sは、クラウドネイティブ時代のゴールデンパートナーのペアとして、多くのエンタープライズオペレーティング環境の標準構成です。ただし、ビジネス規模とマイクロサービスの開発と進化に適応するために、監視対象のオブジェクトの数はずっと増えます。システムまたはアプリケーションのステータスの詳細をより完全に反映するために、インジケーターの粒度はさらに高くなります。より詳細になり、指標の数が増えています。より長い期間でトレンドの変化が見つかった場合、指標データの保持期間はより長くなるはずです。これらすべての変更は、最終的には監視データの量の爆発的な増加につながり、観測製品の保存、クエリ、および計算に大きな圧力をもたらします。

単純なシナリオを通じて、このデータ爆発の結果をより直感的に感じることができます。先月のクラスターの各ノードのCPU使用率の変化をクエリする必要があり、クラスターが30の物理ノードの小規模クラスターであり、各ノードがインジケーターを収集する必要がある平均50のPODを実行するとします。デフォルトの収集間隔である30秒に従って、合計30個の50 = 1500個の収集ターゲットを処理する必要があります。各サンプリングポイントは、1か月のサイクルで1日60 60 * 24/30=2880回キャプチャされます。合計1500*2880 * 30 = 1億3000万のインデックスキャプチャ。ノードエクスポーターを例にとると、1回のベアメタルキャプチャによって吐き出されるサンプルの数は約500であるため、このクラスターによって1か月に生成されるサンプリングポイントの数は約1億3000万*500= 6500億です!実際のビジネスシステムでは、状況はそれほど理想的ではないことが多く、実際のサンプリングポイントの数は1,000億を超えることがよくあります。

このような状況に直面した場合、データの正確性を可能な限り確保することを前提として、ストレージ/クエリ/コンピューティングのコストと効率を最適化するための技術的な手段が必要です。ダウンサンプリングは代表的なアイデアの1つです。

ダウンサンプリングとは

ダウンサンプリングは、データの処理が結合法則に準拠していることを前提としており、複数のサンプリングポイントの値の組み合わせが最終的な計算結果に影響を与えることはありません。Prometheusの時系列データがそのような特性に準拠していることがあります。 。言い換えれば、ダウンサンプリングはデータの解像度を下げることです。アイデアは非常に簡単です。特定の時間間隔内のデータポイントが特定のルールに基づいて1つまたは値のグループに集約される場合、サンプリングポイントの数削減でき、データ量を削減でき、保存されたクエリの計算圧力を軽減できます。したがって、時間間隔、集計ルールの2つの入力が必要です。

ダウンサンプリングの時間間隔については、経験的分析に基づいて、2つの異なるダウンサンプリング時間間隔を定義しました。5分と1時間に加えて、元のデータに加えて、3つの異なる解像度のデータが取得されます。クエリリクエストは、異なる解像度のデータにルーティングされます。 。後続のARMSPrometheusがより長い保存期間オプションを提供するため、新しい時間間隔オプションを追加することもできます。

集計ルールの場合、Prometheusの演算子関数を分析することにより、さまざまな演算子関数を最終的に6種類の数値計算にまとめることができます。

  • max、ベクトルの最大値を計算するために使用されます。max_over_timeなどの一般的な演算子。
  • min、ベクトルの最小値を計算するために使用されます。min_over_timeなどの一般的な演算子。
  • sum、ベクトルの合計値を計算するために使用されます。sum_over_timeなどの一般的な演算子。
  • count、ventor内のポイント数をカウントするために使用されます。count_over_timeなどの一般的な演算子。
  • カウンター、変化率、率、増加などの典型的な演算子を計算するために使用されます。
  • 平均、時間間隔内の各ポイントの平均値を取ります。 

由此可见,对于时间区间内的一系列采样点,我们只需要计算出如上六种类型的聚合特征值,在查询时返回相应时间区间聚合值即可。如果默认的 scrape interval 为 30 秒,五分钟的降采样会将十个点聚合成一个点;一小时的降采样,会将 120 个点聚合成一个点,同样查询涉及到的采样点数,会有数量级的下降,如果 scrape interval 更小,那么采样点缩减的效果会更显著。采样点数的缩减一方面减轻了 TSDB 读取压力,另一方面查询引擎的计算压力也将同步减小,进而有效减少查询耗时。

如何实现降采样

他山之石

其他开源/商业的时序数据存储实现上,有一些也通过降采样功能,对长时间跨度查询做了优化提升,我们也一起了解一下。

  • Prometheus

开源 Prometheus 的存储能力,一直是比较让人诟病的一点,开源的 Prometheus 本身并未直接提供降采样的能力,但提供了 Recording Rule 能力,用户可以使用 Recording Rule 来自行实现 DownSampling,但这样会产生新的时间线,在高基数场景下,反而进一步加剧了存储压力。

  • Thanos

作为知名的 Prometheus 高可用存储方案,Thanos 提供了较为完善的降采样方案。Thanos 中执行 downsmpling 功能的组件是 compactor,他会:

  • 定期从 ojbect storage 中拉取 block(原始的 Prometheus Block,2 小时时间跨度),进行 compaction和downsampling,downsampling 的状态会记录到 block metadata。
  • 压缩和降采样的结果,生成新的 block,写入到 object storage。

1.png

Downsampling 之后的特征值包括 sum/count/max/min/counter,写到特殊的 aggrChunks 数据块里。在做查询时:

  • 原始的聚合算子和函数会转换成特殊的 AggrFunc,对应用于读取 aggrChunks 数据块数据

  • 读取的 block 按照时间排序,优先读取最大 Resolution 的 block

  • M3

2.png

M3 Aggregator 负责在指标存储到 M3DB 前,流式聚合指标,并且根据 storagePolicy 指定指标存储时长和计算窗口的采样间隔。

M3 支持的数据间隔更加灵活,特征值更多,包括 histogram quantile 函数。

  • InfluxDB/Victoria Metric/Context

Victoria Metrics 目前只在商业版本上线了降采样功能,开源版本并未透出。InfluxDB 的开源版本(v2.0 之前)通过类似 Recording Rule 的方式,对已经落盘了的原始数据在存储介质外执行 continuous query 来实现降采样。Context 目前尚不支持降采样。

我们怎么做

市面上的降采样方案各有千秋,我们简单总结了他们的使用成本等用户比较关注的点,比对如下:

3.jpeg

ARMS Prometheus 采用了处理 TSDB 存储块的方式,由后台自动将原始数据块处理为降采样数据块,一方面能取得一个较好的处理性能,另一方面对于终端用户来说,不需要关心参数配置规则维护等等,尽可能的减轻用户运维负担。

此功能已经在阿里云部分 region 上线,并开始定向邀请体验。在即将推出的 ARMS Prometheus 高级版中,将默认集成并提供此功能。

降采样对查询的影响

在我们完成了采样点层面的降采样之后,长时间跨度的查询问题就迎刃而解了么?显然不是的,TSDB 中保存的只是最原始的物料,而用户看到的曲线,还需要经过查询引擎的计算处理,而在计算处理的过程中,我们至少面临这么两个问题:

  • Q1:什么情况下读取降采样数据?是不是降采样后就无法使用原始数据了?
  • Q2:降采样后数据点密度更小,数据更“稀疏”,其查询表现会和原始数据一致么?需要用户调整 PromQL 么? 

对于第一个问题,ARMS Prometheus 会根据用户的查询语句及过滤条件,智能选择适合的时间颗粒度,在数据细节和查询性能之间做出恰当的均衡。

对于第二个问题,首先可以说结论:采集点的密度对结果计算有很大影响,但 ARMS Prometheus 在查询引擎层面屏蔽了差异,用户无需调整 PromQL。 这个影响主要体现在三个方面:与查询语句 duration 间的影响,与查询请求的 step 间的影响,以及对算子本身的影响,下面我们将详细说明这三方面的影响,以及 ARMS Prometheus 在这三方面做的工作。

duration 与降采样计算结果

我们知道,PromQL 中区间向量(Range Vector)查询时,都会带上一个时间区间参数(time duration),用于框定一个时间范围,用于计算结果。比如查询语句http_requests_total{job="prometheus"}[2m]中,指定的 duration 即为两分钟,计算结果时,会将查询到的 time series 以两分钟为单位,分割成若干个 vector,传递给 function 做计算,并分别返回结果。duration 直接决定了 function 计算时能拿到的入参长度,对结果的影响显而易见。

一般情况下,采集点的间隔是 30s 或者更短,只要 time duration 大于这个值,我们就可以确定每个分割出来的 vector 中,都会有若干 samples,用于计算结果。当降采样处理之后,数据点间隔会变大(五分钟甚至一小时),这时候可能就会出现 vector 中没有值的情形,这就导致 function 计算结果出现断断续续的情况。对于这种情况 ARMS Prometheus 会自动调整算子的 time duration 参数来应对,保证 duration 不小于降采样的 resolution,即保证每个 ventor 中都会有采样点,保证计算结果的准确性。

step 与降采样计算结果

duration 参数决定了 PromQL 计算时的 vector 的”长度“,而 step 参数决定了 vector 的”步进“。如果用户是在 grafana 上查询,step 参数实际上是由 grafana 根据页面宽度和查询时间跨度来计算的,以我个人电脑为例,时间跨度 15 天时默认的 step 是 10 分钟。对于某些算子,因为采样点密度下降,step 也可能引起计算结果的跳变,下面以 increase 为例简单分析一下。

正常情况下(采样点均匀,无 counter 重置),increase 的计算公式可以简化为(尾值 - 首值)x duration /(尾时间戳 - 首时间戳),对于一般的场景来说,首/尾点与起/止时间的间隔,不会超过 scrape interval,如果 duration 比 scrape interval 大很多,结果约等于(尾值 - 首值)。假设有一组降采样后的 counter 数据点,如下:

sample1:    t = 00:00:01   v=1 
sample2:    t = 00:59:31   v=1    
sample3:    t = 01:00:01   v=30  
sample4:    t = 01:59:31   v=31 
sample5:    t = 02:00:01   v=31 
sample6:    t = 02:59:31   v=32
...

假设查询 duration 为两小时,step 为 10 分钟,那么我们将会得到分割后的 vector,如下:

slice 1:  起止时间 00:00:00 / 02:00:00  [sample1 ...  sample4] 
slice 2:  起止时间 00:10:00 / 02:10:00  [sample2 ...  sample5] 
slice 3:  起止时间 00:20:00 / 02:20:00  [sample2 ...  sample5]
...

原始数据中,首尾点与起止时间的间隔,不会超过 scrape interval,而降采样之后的数据,首尾点与起止时间的间隔最大可以达到(duration - step)。如果采样点值变化比较平缓,那么降采样后的计算结果与原始数据计算结果不会有较大差别,但是如果某个 slice 区间中值的变化比较剧烈,那么按照上述计算公式(尾值 - 首值)x duration /(尾时间戳 - 首时间戳),会将这种变动等比放大, 最终展示的曲线起伏更剧烈。这种结果我们认为是正常情况,同时在指标变动剧烈(fast-moving counter)的场景下,irate 会更适用一些,这也和官方文档的建议是一致的。

算子与降采样计算结果

有些算子的计算结果与 samples 数量直接相关,最典型的是 count_over_time ,统计时间区间内 samples 数量,而降采样本身就是要缩减时间区间内的点数,所以这种情况需要在 Prometheus engine 中做特殊处理,当发现取用的是降采样数据时,走新的计算逻辑来保证结果的正确。

降采样效果对比

对于用户来说,最终感受到的就是查询速度的提升,但这个提升幅度有多大,我们也通过两个查询实地验证对比下。

测试集群有 55 个 node,共有 pod 6000+,每天上报采样点总数约 100 亿,数据存储周期 15 天。

第一轮比对:查询效率

查询语句:

sum(irate(node_network_receive_bytes_total{}[5m])*8) by (instance)

即查询集群内各个 node 接收到的网络流量情况,查询周期为 15 天。

4.png

图 1:降采样数据查询,时间跨度十五天,查询耗时 3.12 秒

5.png

图 2:原始数据查询,时间跨度十五天,查询超时(超时时间 30 秒)

原始数据因为数据量过大计算超时,未能返回。降采样查询在效率上至少是原始查询的十倍以上。

第二轮比对:结果准确性

查询语句:

max(irate(node_network_receive_bytes_total{}[5m])*8) by (instance) 

即查询各 node 上,接收数据量最大的网卡的流量数据。

6.png

图 3:降采样查询,时间跨度两天

7.png

图 4:原始数据查询,时间跨度两天

最终我们将查询时间跨度缩短到两天,原始数据查询也能较快的返回。对比降采样查询结果(上图)和原始数据查询结果(下图)可见,二者时间线数量和总体趋势完全一致,数据变动比较剧烈的点也能很好的契合上,完全能够满足长时间周期查询的需求。

结语

阿里云于 6 月 22 日正式发布阿里云可观测套件(Alibaba Cloud Observability Suite,ACOS)。阿里云可观测套件围绕 Prometheus 服务、Grafana 服务和链路追踪服务, 形成指标存储分析、链路存储分析、异构构数据源集成的可观测数据层,同时通过标准的 PromQL 和 SQL,提供数据大盘展示,告警和数据探索能力。为IT成本管理、企业风险治理、智能运维、业务连续性保障等不同场景赋予数据价值,让可观测数据真正做到不止于观测。

其中,**阿里云 Prometheus 监控针对多实例、大数据量、高时间线基数、长时间跨度、复杂查询等极端场景,逐步推出了全局聚合查询,流式查询,降采样,预聚合等多种针对性措施。

目前提供 15 天免费试用、Prometheus 监控容器集群基础指标费用减免等促销活动!

点击此处,开通服务~

おすすめ

転載: juejin.im/post/7116529400018894885