Prometheus 原生复合类型存储的现代化演进
概述
Prometheus 的核心优势之一是其高度优化的时序数据库(TSDB),它长久以来采用一种简洁的“经典”存储模型。在此模型下,无论监控指标(Metric)的逻辑类型如何(如计数器、直方图),TSDB 只存储原始的浮点数样本,而复合类型(Composite Types)如直方图、摘要(Summary)则被拆分为多个独立的原始时间序列。这种设计简化了存储实现,但也带来了效率、事务性和可靠性方面的挑战。
近期,Prometheus 社区正推动一次重要的架构演进:在存储层原生支持复合类型的原子化存储。这一变革旨在解决经典模型长期积累的缺陷,为 SRE 提供更可靠、高效且一致的监控数据基础。本文将解析这一演进的核心概念、实践路径及其对可靠性工程的深远影响。
核心概念
经典表示模型(Classic Representation)
在经典模型中,TSDB 存储的是与指标类型无关的“原始样本”(Primitive Samples),即带时间戳的浮点值。指标类型语义由上层协议和工具链(如 PromQL)推断。
- 原始类型:
gauge(默认)、counter(需后缀_total)、info(值恒为 1,带后缀_info)。 - 复合类型:由一组规则关联的原始时间序列构成。例如,一个经典直方图
foo被拆分为多个foo_bucket{le=...}(计数器)、foo_count(计数器)和foo_sum(测量值)时间序列。
局限性:
- 效率低下:复合类型的每个组成部分(如新的桶边界)都会作为独立的唯一时间序列,消耗大量索引空间,压缩率较低。
- 功能受限:数据结构被固定为原始序列的集合,灵活性差(除非使用 JSON 等编码,但这会带来新问题)。
- 事务性缺失:复合类型各部分独立处理。在通过 Remote Write、OTLP 等协议接收或发送数据时,可能只传输了一部分(例如部分桶数据),导致数据不一致,进而引发误报。
- 可靠性存疑:数据消费者无法从存储层获知类型语义,完全依赖名称约定,容易产生误写(例如将
foo_bucket写成 gauge)。
原生表示模型(Native Representation)
原生模型直接在 TSDB 存储层识别并原子化地存储复合样本(如一个完整的直方图结构)。
- 原生直方图(Native Histograms):首次引入的概念。TSDB 可以将带有稀疏和指数桶的直方图作为一个原子复合样本进行存储,而非拆分为多个时间序列。这带来了显著的效率提升(实验证明,使用原生直方图自定义桶 NHCB 可比经典表示节省 30%+ 空间)和数据一致性。
- 原生复合类型的扩展:社区正推动将此原生模式扩展至所有复合类型,包括
summary和stateset,旨在最终完全替代经典模型。
关键演进路径与组件
为实现从经典到原生的平滑过渡,社区正在以下方面进行努力:
- 原生直方图自定义桶(NHCB):允许将经典直方图以原生复合样本格式存储,兼顾经典格式的兼容性与原生存储的效率。
- OpenMetrics 2.0:下一代拉取(Pull)协议规范,其核心变更之一是在文本格式中引入“复合值”,使原生存储的复合类型能够被直接、原子地解析,解决了数据“组合”(Combining)的挑战。
- Remote Write 2.0:允许以原生格式传输直方图数据。未来版本(如 2.1)可扩展以原生格式传输
summary和stateset,确保端到端的数据一致性。 - 消费层兼容模式:这是确保透明迁移的关键。TSDB 和 PromQL 将提供兼容层,当数据以原生格式存储时,仍能通过经典的 PromQL 语法(如
foo_bucket)进行查询,内部会自动“展开”为经典表示。这使得存储层的迁移可以独立于查询和消费工具的升级。
实践
启用原生直方图存储(以 NHCB 为例)
在 Prometheus 采集配置中,可以启用在抓取时将经典直方图转换为原生直方图(NHCB)进行存储。
scrape_configs:
- job_name: 'my-job'
static_configs:
- targets: ['localhost:9090']
# 启用在抓取时将经典直方图转换为NHCB
convert_classic_histograms_to_nhcb: true
此操作在采集端进行组合,解决了远程写入场景下数据碎片化导致的组合难题。转换后的数据将作为名为原指标名(如 foo)的原生复合样本存储。
配置消费层兼容模式(未来)
为保障查询兼容性,未来版本可能通过运行时标志或动态检测,允许对存储为原生格式的指标执行经典查询。例如,以下查询在未来可能对一个已转换为 NHCB 的直方图仍然有效:
# 经典语法将继续工作,即使底层存储的是原生NHCB
histogram_quantile(0.9, sum(foo_bucket{job="a"}) by (le))
这确保了在存储层迁移后,现有的仪表盘、警报规则无需立即修改。
协议演进路径
- 拉取协议:关注 OpenMetrics 2.0 的进展,其中复合值格式将使原生数据在文本层的传输标准化。
- 推送/远程写入协议:采用 Remote Write 2.0 规范以确保传输的直方图等数据能保持原子性。在部署 Prometheus 或 Thanos/Mimir 等系统时,应优先选择支持 Remote Write 2.0 的版本。
SRE 要点
与可靠性、可观测性的关联
- 数据一致性与可靠性:原生模型从根本上解决了复合类型数据在传输和处理中的“部分更新”问题。SRE 可以更可靠地依赖单个数据点进行告警和决策,减少了因数据不一致导致的误报,这是提升系统可靠性的直接体现。
- 性能与可扩展性:更高效的存储降低了资源消耗,使监控系统本身更具可靠性和可扩展性,能够处理更高基数或更复杂的指标。
- 可观测性质量:原子化的数据保证了聚合(如
sum、avg)和分析(如百分位计算)的准确性,提升了可观测性的信号质量。
最佳实践与常见反模式
- 渐进式迁移:利用 NHCB 和兼容模式,逐步迁移核心服务的直方图监控,无需一次性修改所有应用和查询。
- 监控协议与存储格式:在升级 Prometheus 或远程存储系统时,将支持 Remote Write 2.0 和 OpenMetrics 2.0 列为评估项。
- 反模式:避免依赖“经典模型即将废弃”的猜测而强行全面重写现有指标或查询。应采用社区推荐的兼容迁移路径。
- 反模式:避免在自定义集成中继续假设所有复合类型都由多个时间序列组成,这可能导致未来与原生格式不兼容。
相关指标(SLI/SLO/SLA)
- 存储效率 SLI:可以监控原生格式与经典格式在相同数据集下的存储空间占用比例(例如,目标:原生直方图存储空间 ≤ 经典格式的 70%)。
- 数据完整性 SLI:通过校验和或采样对比,监控复合类型数据在采集、转换、存储、查询链路中的完整性,确保原子性未被破坏。
- 查询兼容性 SLI:监控使用经典查询语法的现有告警规则和仪表盘的运行成功率,确保迁移期间无破坏性中断。
- SLO/SLA 影响:存储效率和数据一致性的提升,直接支撑着更严格的监控数据可用性 SLO(例如,从 99.9% 提升到 99.95%),从而支撑更优的最终用户 SLA。
相关页面链接:[[data-model]], [[promql]], [[observability]], [[remote-write]], [[native-histograms]]