直方图 vs 摘要
博客文章在发布后不会更新。这篇文章已经发布一年多了,其内容可能已过时,部分链接可能无效。在依赖任何信息之前,请务必核实。
在很多方面,直方图和摘要看起来非常相似。它们都将许多数据点汇总成一个数据结构,以便进行高效的处理、传输和存储。它们也可以用来跟踪任意分位数,如数据的中位数或p99。那么它们有什么区别呢?让我们深入了解一下。
直方图
由于我刚发布了一篇关于直方图及其用途的文章,这里我只会提供一个简要的总结。直方图是一种描述数据点分布的数据结构。例如,可以收集HTTP端点的所有响应时间,并将其描述为一个拥有10个区间、范围从0到1000毫秒的直方图。每个区间计算落入其范围内的请求数量。

由此我们可以估算φ分位数,例如90%分位数。我们知道有1260个请求,所以排名第1134位(1260 * .90)的请求代表90%分位数。通过累加区间计数直到超过该排名,我们可以计算出该请求落入第8个区间(300 <= x < 500)。最后,使用区间内24(1134 - 1110)的相对排名,通过线性插值,我们可以估计p90值为360毫秒(300 + ((24 / 80) * (500 - 300)))。重要的是要知道这是一个估算,可能会有高达60毫秒(360 - 300)的误差,相对误差为17%(60 / 360)。通过配置更多更小的区间来围绕你的SLO值,可以减轻这个误差,但永远无法消除。
直方图的一个重要属性是它们是可聚合的,这意味着只要区间边界对齐,任意数量的直方图都可以合并成一个直方图,而不会丢失数据或精度。这意味着任意数量的主机可以向服务器报告直方图数据结构,服务器可以聚合并计算所有这些直方图的分位数,就好像它们是由单个主机报告的一样。通过收集1个或多个主机长时间的直方图数据,开发人员可以深入了解他们的数据分布以及该分布如何随时间变化。
摘要
摘要的工作方式几乎相反。当配置摘要时,它会被赋予一个需要跟踪的φ分位数、一个可接受的误差范围和一个衰减率。例如,一个摘要可能以5分钟的衰减率跟踪p99 ± 0.5%的误差。这里的数学更复杂,此处不详述,但一个重要的区别是该值是在发送到服务器之前在客户端计算的。最重要的后果是来自多个客户端的摘要无法聚合。另一个缺点是,你无法查询任意的φ分位数,只能查询你已配置并预先收集好的分位数。
考虑到这些缺点,摘要也有一些优点。首先,它们以一小部分的性能开销为代价,大大降低了传输、存储和服务器处理成本。在我们上面的直方图示例中,分布被表示为12个独立的时间序列:每个区间一个计数器+一个超出范围值的区间+所有值的总和。这是针对单个、相对适中的直方图,没有属性来增加基数。相比之下,摘要只有一个预计算p99值的时间序列。其次,它们具有非常低且可配置的相对误差率。在上面我们直方图的例子中,我们有17%的潜在相对误差,而我们的摘要保证在±0.5%的精度范围内。
那么你应该选择哪一个?
令人失望的答案是“这取决于”,没有一刀切的解决方案。如果你需要聚合来自多个来源的数据,那么直方图可能是正确的选择。如果你正在收集大量独立的指标,并且有非常严格的SLO,或者你的Prometheus服务器资源非常受限,那么摘要可能是适合你的选择。也许你理想的解决方案是混合使用,一些直方图用于灵活查询,一些摘要用于高精度、低成本的警报。只有你了解自己系统的细节,并围绕它设计一个准确、灵活并满足你特定需求的观测解决方案。关键在于了解可用工具的优势和局限性,以便做出明智的决定。
奖励环节:原生/指数直方图
我计划写一篇更长的文章来介绍这个,所以这里我会简短说明,但直方图的许多关键缺点可以通过指数直方图得到缓解,在Prometheus中称为原生直方图。从v2.40.0开始,它们在Prometheus中是一个实验性功能,并且在OpenTelemetry规范v1.17.0中已稳定。指数直方图具有几个优点:
- 非常高效的数据收集和传输
- 每个直方图创建的时间序列数量恒定(且更少)
- 非常低的相对误差率
- 自动的区间边界,使其更易于配置和使用
这些优势是通过根据比例因子定义区间边界来实现的,通过智能地调整区间大小来适应分布的变化,而不是传统的方法定义显式区间。如果你对当前直方图和摘要的现状不满意,我鼓励你尝试指数直方图。截至目前,还没有关于原生直方图的官方Prometheus文档,但如果你继续关注,我计划在未来几天内提供详细的解释。
在此之前,这里有一些我发现有用的演讲
- PromCon EU 2022 - Prometheus 中的原生直方图 - Ganesh Vernekar
- KubeCon EU 2023 - 生产环境中的 Prometheus 原生直方图 - Björn Rabenstein, Grafana Labs
- 在 Prometheus 中使用 OpenTelemetry 的指数直方图 - Ruslan Kovalov & Ganesh Vernekar
本文的一个版本最初发布在作者的博客上。