现代化 Prometheus:复合类型的原生存储

发布: (2026年2月14日 GMT+8 08:00)
15 分钟阅读

Source: Prometheus Blog

请提供您希望翻译的具体文本内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。

在过去的一年里,Prometheus 社区一直在努力实现一些以前会被视为有争议或不可行的有趣且雄心勃勃的变更。虽然这些在外部可能知之甚少(例如,它不是 OpenClaw Prometheus 插件,抱歉 🙃),但 Prometheus 开发者正自然而然地将 Prometheus 引向一个特定且连贯的未来。一步步地,我们意外地接近了那些我们从未想象过的、作为开源项目能够实现的目标!

这篇文章(希望!)作为一系列博客文章的开端,分享一些可能令新老 Prometheus 用户和开发者感到兴奋的雄心勃勃的转变。在本文中,我想重点讨论 复合类型的原生存储 的想法,这正在整理多年来堆积的许多挑战。务必查看文中提供的内联链接,了解如何提前采用其中的一些变更或进行贡献!

注意: 免责声明:本文旨在提供一个有趣的概览,基于我作为 Prometheus 维护者的个人视角。文中提到的一些变更尚未(或仍未)得到 Prometheus 团队的正式批准;其中一些也未在生产环境中验证。
备注: 本文由人工撰写;AI 仅用于外观和语法的修正。

经典表示:原始样本

正如你可能知道的,Prometheus 数据模型(包括服务器、PromQL、协议)支持 gauge、counter、histogram 和 summary。OpenMetrics 1.0 在此基础上扩展了 gaugehistograminfostateset 类型。

令人印象深刻的是,长期以来 Prometheus 的 TSDB 存储实现拥有一个明确简洁的数据模型。TSDB 允许存储和检索 带字符串标签的原始样本,这些样本仅包含 float64 值和 int64 时间戳。它对指标类型完全不做假设。

指标类型是基于 TSDB 之上为人类和 PromQL 的最佳实践工具隐式定义的。为简化起见,我们把这种存储类型的方式称为 经典模型(或表示)。在该模型中:

原始类型

类型描述
gauge“默认” 类型,没有特殊规则——仅是带标签的浮点样本。
counter名称应以 _total 为后缀,以便人类理解其语义。
foo_total 17.0
info指标名称必须以 _info 为后缀,且始终取值为 1

复合类型

有趣的部分来了。在经典表示中,复合指标被表示为一组原始浮点样本。

Histogram – 一组具有特定必需后缀和 le 标签的计数器:

foo_bucket{le="0.0"}      0
foo_bucket{le="1e-05"}    0
foo_bucket{le="0.0001"}   5
foo_bucket{le="0.1"}      8
foo_bucket{le="1.0"}     10
foo_bucket{le="10.0"}    11
foo_bucket{le="100000.0"}11
foo_bucket{le="1e+06"}    15
foo_bucket{le="1e+23"}   16
foo_bucket{le="1.1e+23"} 17
foo_bucket{le="+Inf"}    17
foo_count                17
foo_sum               324789.3

gaugehistogramsummarystateset 类型遵循相同的逻辑——一组特殊的 gauge 或 counter 组合成单个指标。

经典模型为 Prometheus 项目提供了良好的支持。它显著简化了存储实现,使 Prometheus 成为最优化的开源时序数据库之一,并且基于相同数据模型的分布式版本已在 CortexThanosMimir 等项目中出现。

经典模型的局限性

类别问题
效率复合类型的开销,因为每个新数据(例如新 bucket)都会占用宝贵的索引空间(它是一个新的唯一序列),而样本则更易压缩(很少变化,面向时间)。
功能性限制了存储数据的形状和灵活性(除非使用 JSON 编码的标签,但这有巨大的缺点)。
事务性复合类型的原始部件(独立计数器)被独立处理。写入隔离在抓取时有效,但在 remote‑write、OTLP 或长期分布式存储时会失效。直方图可能只部分发送,导致误报或漏报。
可靠性TSDB 数据的使用者基本上只能猜测类型语义。没有任何限制阻止用户写入 foo_bucket 仪表或 foo_total 直方图。

对复合类型的本地存储一瞥

经典模型在引入 本地直方图 后受到挑战。TSDB 被扩展以存储除普通浮点数之外的复合直方图样本。我们倾向于称其为 本地直方图,因为 TSDB 现在可以 本地存储完整(稀疏且指数型)直方图作为原子复合样本

当时的普遍共识是就此止步。通常用于取代“经典”直方图的特殊高级直方图使用复合样本,而其余指标仍然使用经典模型。让其他复合类型与新的本地模型保持一致会对用户造成极大干扰,工作量和风险都太大。

常见的反驳意见是,用户最终会自然迁移其经典直方图,并且鉴于本地直方图更强大的分桶能力和更低的成本,摘要的作用会变得不那么重要。

然而,迁移到本地直方图已知需要时间:

  • PromQL 更改 – 查询本地直方图时需要进行轻微的语法调整。
  • 客户端更改 – 应用程序必须定义新指标或编辑现有指标以使用本地直方图。
  • 遗留软件 – 老旧软件可能会无限期地在生产环境中运行,永不迁移。

因此,Prometheus 不能简单地废弃经典直方图;所有下游解决方案必须继续支持经典模型。

本地直方图、NHCB 与完整复合样本模型的路径

背景

本地直方图将 TSDB 及其生态系统推向了一种新的 复合样本 模式。其中一些变化可以适用于所有复合类型,而本地直方图让我们看到了原生支持的诸多好处。

“是否可以添加现有复合指标的本地对应物来替代它们,理想情况下是透明的?”

在 2024 年,为了事务性和效率,我们引入了 本地直方图自定义桶 (Native Histogram Custom Buckets, NHCB) —— 一种将经典直方图与显式桶 原生 存储的概念,复用本地直方图复合样本的数据结构。

  • 效率 – NHCB 至少比经典表示高 30 %,且功能等价。

  • 采纳挑战 – 两个实际问题减缓了推广:

    1. 展开(NHCB → 经典)非常简单。
    2. 合并(经典 → NHCB)往往不可行。
      • 在抓取时进行转换成本高。
      • 远程写入的 “push” 可能会把一个直方图拆分到不同的分片或顺序消息中,导致合并不可能。
      • 这就是为什么 OpenTelemetry‑collector 用户在 prometheusreceiver 上看到额外开销——OpenTelemetry 模型严格遵循复合样本模型。

消费差异(PromQL)

经典直方图示例

foo_bucket{le="0.0"} 0
# …
foo_bucket{le="1.1e+23"} 17
foo_bucket{le="+Inf"} 17
foo_count 17
foo_sum 324789.3

NHCB 表示

指标名称现在是 foo(没有 _bucket 后缀)。

# 新语法(原生)
histogram_quantile(0.9, sum(foo{job="a"}))

# 旧语法(展开后)
histogram_quantile(0.9, sum(foo_bucket{job="a"}) by (le))

后果

  • 文本格式的 “所见即所查” 规则被破坏(直到 OpenMetrics 2)。
  • 类似的问题也出现在其他 Prometheus 输出中(联邦、远程读取、远程写入)。

注意: Prometheus 客户端数据模型(SDK)和 PrometheusProto 抓取协议已经使用了复合样本模型!

透明本地表示

社区方向

Prometheus 社区似乎正趋向于两个想法:

  1. 在存储层迁移到完整的复合样本模型 —— 以获得所有相关收益。
  2. 允许用户在不破坏消费层的情况下切换(例如在抓取时)从经典模式到本地模式 —— 简化迁移,避免双模式协议更改,并尽快弃用经典模型。

您可以参与的正在进行的工作

计划目标状态
本地摘要 & 状态集消除所有复合类型的经典模型。初期讨论——欢迎贡献。
OpenMetrics 2.0整合并改进拉取协议;在文本格式中使用复合值,使支持本地复合的存储解析变得极其简单。文本格式仍将在默认抓取时 展开 为经典模式(不产生破坏性更改)。
Remote Write 2.0以本地形式传输直方图(仍支持经典)。未来版本(如 2.1)可能会加入本地摘要和状态集。需要稳定——欢迎贡献。
兼容模式将存储的复合样本转换回经典表示,以供消费(PromQL、联邦、remote‑read 等)。已有原型;仍有边缘案例待处理。

PromQL 兼容性示例

# New syntax – works directly on the NHCB "foo"
histogram_quantile(0.9, sum(foo{job="a"}))

# Old syntax – expands the NHCB to classic representation
histogram_quantile(0.9, sum(foo_bucket{job="a"}) by (le))

替代方案(例如特殊标签或注释)也在讨论中。

完全实现后,管道可以在任何阶段 透明 地切换到本地形式。

摘要

将 Prometheus 移植到 原生复合类型世界 是一项具有挑战性的工作,需要时间:

  • 性能特征 从统一、可预测的样本大小转变为取决于指标类型的大小。
  • 代码架构 变得更为复杂——维护多种样本类型已经被证明是困难的。

尽管如此,社区正积极开展必要的协议更新、兼容层以及存储改动。无论是对 OpenMetrics 2.0、Remote Write 2.0,还是对兼容模式的贡献,都对确保此转变平稳且可持续至关重要。

更新与机会

为什么这很重要

最近的工作发现了一条 清晰、可行的路径,在以下方面带来明显好处:

  • 功能性
  • 事务性
  • 可靠性
  • 效率

这些改进预计 在相对不久的将来 实现——非常令人兴奋!

如何参与

  • 私信 我在 Slack 上。
  • #prometheus‑dev Slack 频道提问。
  • 在相关 issue 上评论,创建 PR,并 审阅 PR(最有影响力的工作!)。

Prometheus 在 KubeCon EU 2026 – 阿姆斯特丹

时间内容
展位参观 Prometheus KubeCon 展位
Wed Mar 25 2026, 16:00贡献工作坊
Thu Mar 26 2026, 13:45Prometheus V3 – 一年回顾:OpenMetrics 2.0 及更多! 会议

没有承诺,但欢迎帮助!以下是我们计划在后续文章中覆盖的领域的非详尽、随机顺序列表。

未来主题(进行中)

  • 原生 start‑timestamp 功能 – 干净地解锁原生增量时间性,无需 hack(例如,重复使用 gauge、额外的度量类型,或像 __temporality__ 这样的标签注解)。
  • Prometheus 指标的可选模式化 – 解决指标命名/形状的稳定性问题,基于 OpenTelemetry 语义约定构建。
  • 元数据存储改进 – 提升 OpenTelemetry 实体和资源属性的存储/使用体验。
  • 扩展的 scrape/pull 协议 – 使 Prometheus 与最近的 OpenMetrics 所有权转移保持一致。
  • TSDB Parquet 项目 – 来自三个 LTS 项目组(Cortex、Thanos、Mimir)的联合倡议,面向高基数使用场景。
  • PromQL 扩展 – 试验管道、变量以及新的 SQL 转译思路。
  • 治理变更 – 项目治理的持续更新。

在开源世界再会!

欢迎随时联系、贡献,或仅仅关注我们的旅程。你的参与让这一切成为可能。

0 浏览
Back to Blog

相关文章

阅读更多 »

Google的4个黄金信号

介绍 在本文中,我们将讨论巩固 SRE 的一个重要里程碑:Google 的四大黄金信号(Golden Signals)。它们是基于实践经验的成果。