直方图 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个或多个主机收集直方图,开发人员可以深入了解数据的分布以及这种分布随时间的变化情况。

摘要

摘要的工作方式几乎相反。配置摘要时,需要指定要跟踪的φ分位数、可接受的误差范围和衰减速率。例如,摘要可以跟踪p99±0.5%的值,衰减速率为5分钟。数学运算比较复杂,这里不会详细讨论,但一个重要的区别是值是在客户端计算后发送到服务器的。这样做最重要的结果是多个客户端的摘要_无法聚合_。另一个不利之处是,您只能查询那些您事先配置和收集的φ分位数,而不能查询任意φ分位数。

尽管存在这些不利之处,摘要仍具有一些优势。首先,它们在客户端上会产生一小部分性能损失,但在传输、存储和服务器处理成本方面却能显著降低。在上面的直方图示例中,分布表示为12个单独的时间序列:每个桶的计数器+一个用于超出范围值的桶+所有值的总和。这只是一个单独的、相对适度的直方图,没有属性可增加基数。相比之下,摘要只是一个用于预计算p99值的单个时间序列。其次,它们具有非常低且可配置的相对误差率。在上面的直方图示例中,我们可能存在17%的相对误差,而我们的摘要保证在±0.5%的准确度范围内。

那么应该选择哪种?

令人失望的答案是“这取决于情况”,没有一种通用的解决方案。如果您需要聚合来自多个来源的数据,则直方图可能是正确的选择。如果您收集大量单独的指标,并有非常严格的SLOs,或者您的Prometheus服务器资源非常有限,那么摘要可能是适合您的选择。也许您的理想解决方案是一种混合模式,既有某些直方图用于灵活查询,又有一些摘要用于高准确度、低成本的告警。只有您才能了解自己系统的内外情况,并设计一个合适的可观察性解决方案,精确、灵活并适应您特定需求的。关键是要了解可用工具的优势和限制,以便做出明智的决策。

附加内容:本地/指数直方图

我计划撰写一篇更长的文章来详细介绍这个问题,所以我会简要地介绍一下,指数直方图,也称为Prometheus中的本地直方图,可以缓解许多直方图的关键不足之处。自从v2.40.0版本起,它们作为实验特性可用于Prometheus,并且在OpenTelemetry规范中的v1.17.0版本中已稳定下来。指数直方图具有以下几个优点:

  • 非常高效的数据收集和传输
  • 每个直方图创建恒定数量的时间序列(较少的时间序列)
  • 非常低的相对误差率
  • 自动的桶边界,使其配置和使用更简单

通过根据一个比例系数来定义桶的边界,智能地调整桶大小以适应分布的变化,而不是传统的定义显式桶的方法,实现了这些优点。如果您对当前的直方图和摘要的情况不满意,我鼓励您尝试一下指数直方图。截至目前为止,Prometheus没有关于本地直方图的官方文档,但是如果您保持关注,我计划在未来几天内添加一份详细的说明。

在此之前,这里有一些我发现有帮助的讲座:

本文的一个版本最初发布在 作者的博客 上。