为什么使用直方图?

直方图是一个多值计数器,用于总结数据点的分布。例如,一个直方图可能有3个计数器,分别计算负数、正数和零值的出现次数。给定一系列数字,3-9760-1,直方图将计算出2个负数、1个零值和3个正数。单个直方图数据点通常被表示为条形图。

以条形图表示的直方图数据点

上面的示例只有3个可能的输出值,但单个直方图通常会有更多。实际应用通常会每分钟导出一个直方图,该直方图总结了前一分钟的度量。通过这种方式使用直方图,您可以研究数据分布随时间的变化。

直方图的用途是什么?

直方图有许多用途,但它们的强大之处在于能够高效地回答关于数据分布的查询。这些查询通常以某种形式出现,比如“上一分钟的中位数响应时间是多少?”这些被称为φ-分位数,通常使用简写表示,如p50代表50th百分位数或0.5-分位数,也称为中位数。更一般地,φ-分位数是在N个观察值中排名为φ*N的观察值。

直方图为什么有用?

在可观察性中,直方图的常见用途之一是定义服务水平目标(SLOs)。一个SLO的示例可能是“所有查询的>=99%响应时间应小于30毫秒”或“90%的页面加载应在首次绘制后的100毫秒内成为可交互状态”。

在下面的图表中,您可以看到一些请求的p50p90p99响应时间随时间的变化。从数据中可以看出,大约有50%的请求在20-30毫秒或更短的时间内处理,90%的请求在约80毫秒以下完成,而99%的请求在约90毫秒以下完成。您可以很快地看到至少50%的用户接收到非常快的响应时间,但几乎所有用户的响应时间都在90毫秒以下。

以线图绘制的p99、p90和p50

其他度量类型

如果您已经根据其他度量定义了SLOs,您可能考虑将SLOs定义为基于测量仪表或计数器。这种方法可以奏效,但它要求在了解数据分布之前定义SLOs,并需要有意义的数据收集实现。它也是不灵活的;如果您决定将SLO从90%的请求更改为99%的请求,您必须进行代码更改并发布,然后等待旧数据过期并收集足够的新数据以进行有用的查询。因为直方图将数据建模为从开始到结束的分布,所以您可以简单地更改查询并获得已经收集的数据上的答案。特别是对于指数直方图,可以以非常低的相对误差率和最小的资源消耗,在客户端和分析后端上进行任意分布查询。

不使用直方图来定义SLOs的不灵活性还会影响您在SLO违规时评估影响的能力。例如,假设您正在收集一个计算某个度量的p99的测量仪表,并基于此定义了一个SLO。当SLO违反并触发警报时,您如何知道它实际上只影响了1%的查询、10%还是50%?通过查询您感兴趣的百分位数,直方图可以回答这个问题。

另一个选择是将每个感兴趣的分位数作为测量仪表进行收集。一些系统(如Prometheus)原生支持这种方式,使用一种被称为摘要的度量类型。摘要确实可以工作,但它们与测量仪表和计数器遇到相同的不灵活性,需要您事先决定要收集哪些分位数。它们也无法进行聚合,这意味着无法准确计算出两个单独主机各自报告的p90

其他数据源和度量类型

您可能会问:“为什么要报告一个单独的度量,而不是从现有的日志和跟踪数据计算得到?”虽然对于某些用例(如响应时间)来说,这可能是可行的,但并不一定适用于所有用例。即使可以从现有数据中计算出分位数,您可能会遇到其他问题。您需要确保可观察性后端能够在线查询和分析大量的现有数据,或者能够在摄入时对其进行索引和分析。如果对日志和跟踪进行采样或使用数据保留策略使数据过时,您需要确保这些因素不会影响导出的度量,或者对其进行适当加权,否则可能无法准确评估您的SLOs。根据采样策略,这甚至可能是不可能的。如果适用,使用直方图是避免这些细微问题的一种方式。

本文的修订版本最初发表在作者的博客上。