2. Prometheus 核心架构:Pull 模型、时序数据库、PromQL 基础、数据模型
本章深入剖析 Prometheus 的四大核心支柱:Pull 模型、时序数据库 (TSDB)、PromQL 基础与数据模型。理解这些是构建可靠 SLO 监控与性能调优的基石。
2.1 数据模型:时序数据的原子结构
Prometheus 将所有采集的数据定义为时间序列 (Time Series)。一个时间序列由 Metric Name (指标名) 和一组 Labels (标签) 唯一标识。
| 组件 | 说明 | 示例 |
|---|---|---|
| Metric Name | 描述被测量内容的通用名称,必须符合正则 [a-zA-Z_:][a-zA-Z0-9_:]* |
http_requests_total |
| Labels | 键值对,用于维度区分。每个序列的标签组合必须唯一 | {job="api-server", method="GET", status="200"} |
| Sample (样本) | 时间戳 (int64 ms) + 值 (float64) | @1710000000 1024 |
设计原则:标签是 Prometheus 多维度数据模型的灵魂。通过标签组合,你可以将
http_requests_total 按 method、status、endpoint 任意维度聚合,无需预先定义维度组合。
2.2 Pull 模型:主动拉取 vs 被动推送
Prometheus 采用 Pull (拉取) 模式,由 Server 端主动向 Exporter 或目标应用暴露的 HTTP 端点 (/metrics) 抓取数据。这与传统的 Push (推送) 模型有本质区别。
Pull 模型核心优势:
- 健康探测:如果 Server 拉取失败,可直接判定目标实例宕机或网络故障。
- 控制数据流:Server 端控制抓取频率和生命周期,避免下游系统过载。
- 简化配置:无需在应用侧配置数据接收端地址,只需暴露端口。
2.3 时序数据库 (TSDB):高效存储与压缩
Prometheus 内置高性能 TSDB,专为时序数据写入和查询优化。其核心设计包括 Block (数据块) 和 Compaction (压缩合并)。
- Block 结构:每个 Block 包含 2 小时的数据窗口,内部按 Series 组织 Chunks。Block 不可变,写入后只读。
- Compaction 机制:后台将多个小 Block 合并成大 Block,删除已删除的 Series,并执行 Dedup (去重) 和 Downsample (降采样)。
- 内存与磁盘:最新数据常驻内存 (WAL + In-Memory Chunks),定期刷盘。查询时优先从内存读取。
性能调优关键:TSDB 的写入吞吐量受限于磁盘 I/O 和 CPU。当 Series 基数 (Cardinality) 过高(例如标签值组合超过 100 万),会导致内存膨胀和查询缓慢。这是 SRE 必须监控的指标。
2.4 PromQL 基础:查询语言核心
PromQL (Prometheus Query Language) 是数据消费的入口。掌握基础语法是编写 SLO 表达式的前提。
2.4.1 数据类型
- Instant Vector (瞬时向量):一组时间序列,每个序列包含一个最新样本。例如
http_requests_total{job="api"}。 - Range Vector (范围向量):一组时间序列,每个序列包含一段时间范围内的样本。例如
http_requests_total{job="api"}[5m]。 - Scalar (标量):一个简单的数字浮点值。
- String (字符串):当前未使用。
2.4.2 常用选择器与操作符
| 类型 | 语法 | 示例 |
|---|---|---|
| 标签匹配 | = (等于), != (不等于), =~ (正则匹配), !~ (正则排除) |
{method=~"GET|POST"} |
| 算术操作符 | +, -, *, /, %, ^ |
rate(http_requests_total[5m]) * 1000 |
| 聚合操作符 | sum(), avg(), max(), min(), count(), topk() |
sum by (status) (rate(http_requests_total[5m])) |
| 函数 | rate(), irate(), increase(), histogram_quantile() |
histogram_quantile(0.99, ...) |
SRE 实战提示:在 SLO 计算中,
rate() 和 histogram_quantile() 是最常用的函数。rate() 计算每秒平均增长率,适合 Counter 类型;histogram_quantile() 用于从 Histogram 中计算延迟分位数。
2.5 核心架构总结:组件协作关系
下图展示了 Prometheus 核心组件如何协同工作,从数据采集到查询展示的完整链路。
2.6 性能调优关注点
作为 SRE,在理解架构后,需要关注以下关键指标以保障 Prometheus 自身性能:
| 关注维度 | 关键指标 | 调优方向 |
|---|---|---|
| Series 基数 | prometheus_tsdb_head_series |
控制标签数量,避免高基数标签 (如 user_id, request_id) |
| 写入延迟 | prometheus_tsdb_wal_fsync_duration_seconds |
使用 SSD,调整 --storage.tsdb.wal-segment-size |
| 查询性能 | prometheus_engine_query_duration_seconds |
优化 PromQL,避免大范围未经聚合的查询 |
| 内存使用 | process_resident_memory_bytes |
限制内存上限 --storage.tsdb.retention.size |
最佳实践:在 SLO 作业中,我们通常使用
rate() 和 histogram_quantile() 构建核心指标。务必在 PromQL 中通过 sum by (important_label) 减少返回的序列数量,这是最有效的查询优化手段。