Prometheus 数据模型详解
Prometheus 的数据模型是其最核心的设计之一,它决定了指标如何存储、查询和分析。与传统监控系统不同,Prometheus 采用多维时间序列模型(Multi-dimensional Time Series Model),使得监控数据具有极强的灵活性和表达能力。
本文将深入解析 Prometheus 的数据模型,包括 时间序列结构、指标类型、样本格式、标签(Labels)语义、存储机制 等关键概念。
一、核心概念:时间序列(Time Series)
在 Prometheus 中,每一条监控数据都是一条时间序列。
什么是时间序列?
一个时间序列是一个由 指标名称 + 标签集 唯一标识的、随时间变化的数值序列。
示例
http_requests_total{job="api-server", instance="192.168.1.10:8080", method="GET", status="200"}
→ [ (t₀, 10), (t₁, 12), (t₂, 15), ... ]
http_requests_total:指标名称{job="api-server", ...}:标签集(Labels)- 每个
(timestamp, value)是一个样本(Sample)
✅ 每个唯一的
(metric name + labels)组合对应一条独立的时间序列。
二、数据模型组成要素
Prometheus 的数据模型由以下四个核心部分构成:
| 组成部分 | 说明 |
|---|---|
| 1. 指标名称(Metric Name) | 标识指标的含义,如 http_requests_total |
| 2. 标签(Labels) | 键值对,用于添加维度(如 method="GET") |
| 3. 样本(Sample) | (timestamp, value) 数据点 |
| 4. 时间戳(Timestamp) | 毫秒级精度的时间戳 |
三、指标名称(Metric Name)
命名规范
- ✅ 推荐:小写字母 + 下划线分隔(snake_case)
- ✅ 语义清晰,反映指标含义
- ❌ 避免使用特殊字符或空格
常见命名模式
| 类型 | 示例 |
|---|---|
| Counter(计数器) | http_requests_total, job_success_total |
| Gauge(仪表) | memory_usage_bytes, cpu_temperature_celsius |
| Histogram(直方图) | http_request_duration_seconds |
| Summary(摘要) | rpc_duration_seconds |
⚠️ Prometheus 会自动为 Histogram 添加
_bucket,_sum,_count后缀。
四、标签(Labels)——多维模型的核心
标签是 Prometheus 实现多维监控的关键,相当于“维度”或“属性”。
1. 标签的作用
- 对指标进行切片(Slice)
- 聚合(Aggregate)
- 过滤(Filter)
- 分组(Group)
2. 内置保留标签
Prometheus 自动添加或保留一些特殊标签:
| 标签名 | 说明 |
|---|---|
job | 抓取任务名称(来自 scrape_configs.job_name) |
instance | 目标实例地址(如 192.168.1.10:8080) |
__name__ | 指标名称(内部使用) |
le | Histogram 的 bucket 上限(less or equal) |
quantile | Summary 的分位数(如 0.99) |
✅
job和instance是强制标签,几乎所有时间序列都包含。
3. 自定义标签
用户可添加任意自定义标签:
http_requests_total{
job="api",
instance="10.0.0.1:8080",
method="POST",
handler="/api/users",
status="500",
version="v1.2.0"
} 42
常见自定义标签键
| 标签键 | 示例值 | 说明 |
|---|---|---|
method | GET, POST | HTTP 方法 |
status | 200, 500 | 响应状态码 |
handler | /api/users | 请求路径 |
cluster | prod-us | 集群名称 |
env | prod, staging | 环境 |
service | user-service | 服务名 |
region | us-east-1 | 地域 |
4. 标签设计最佳实践
| 原则 | 说明 |
|---|---|
| ✅ 低基数(Low Cardinality) | 标签取值应有限(如 status 只有几十种) |
| ✅ 语义清晰 | 键名应通用、易懂(避免 tag1, type) |
| ✅ 避免高基数 | 禁止使用 user_id, order_id, ip, trace_id |
| ✅ 统一命名 | 团队内约定标签键(如 env 而非 environment) |
| ✅ 使用 relabel_configs 清理 | 删除无用标签,减少存储开销 |
🚫 高基数标签是导致 Prometheus 内存溢出(OOM)和性能下降的最常见原因!
五、样本(Sample)结构
每个样本是一个 (timestamp, value) 对:
timestamp:毫秒级 Unix 时间戳value:64 位浮点数(支持整数、小数)
示例
# HELP http_requests_total Total number of HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",status="200"} 1024 1678886400000
http_requests_total{method="GET",status="200"} 1025 1678886415000
- 第一个样本:时间
1678886400000(2023-03-15 00:00:00 UTC),值1024- 第二个样本:15 秒后,值
1025
六、指标类型(Metric Types)
Prometheus 支持四种核心指标类型,每种类型对应不同的数据语义和使用场景。
1. Counter(计数器)
- 用途:单调递增的计数器,记录事件发生次数。
- 特点:
- 只能增加(或重置为 0)
- 用于
rate(),increase()计算速率
- 示例:
http_requests_total{method="GET"} 1024
✅ 适用场景:请求总数、错误数、消息发送数
2. Gauge(仪表)
- 用途:测量当前瞬时值,可增可减。
- 特点:
- 反映当前状态
- 无需计算
rate()
- 示例:
memory_usage_bytes{region="us"} 536870912 temperature_celsius{sensor="cpu"} 65.3
✅ 适用场景:内存使用、温度、队列大小、库存余额
3. Histogram(直方图)
- 用途:记录事件的数值分布(如请求耗时、响应大小)。
- 特点:
- 将值分配到预定义的 bucket(桶) 中
- 自动生成三个时间序列:
<name>_bucket{le="x"}:小于等于x的样本数<name>_count:总样本数<name>_sum:所有样本值之和
- 示例:
http_request_duration_seconds_bucket{le="0.1"} 100 http_request_duration_seconds_bucket{le="0.5"} 150 http_request_duration_seconds_bucket{le="+Inf"} 160 http_request_duration_seconds_count 160 http_request_duration_seconds_sum 45.6
✅ 用于计算分位数:
histogram_quantile(0.99, ...)
4. Summary(摘要)
- 用途:记录事件的分位数分布(如 p50, p95, p99)。
- 特点:
- 在客户端计算分位数
- 生成:
<name>{quantile="0.5"}:中位数<name>{quantile="0.99"}:99 分位数<name>_count,<name>_sum
- 示例:
rpc_duration_seconds{quantile="0.5"} 0.01 rpc_duration_seconds{quantile="0.9"} 0.05 rpc_duration_seconds{quantile="0.99"} 0.1 rpc_duration_seconds_count 1000 rpc_duration_seconds_sum 12.3
⚠️ 与 Histogram 对比:
- Summary:客户端计算,不支持聚合
- Histogram:服务端计算,支持跨实例聚合(推荐)
七、数据存储格式(TSDB 内部表示)
Prometheus 使用 TSDB(Time Series Database) 存储数据,其内部结构优化了写入和查询性能。
存储单元:Block
- 数据按 2 小时 block 存储在磁盘
- 每个 block 包含:
chunks/:压缩的时间序列数据块index:倒排索引,支持快速标签查询meta.json:元信息(时间范围、版本等)
内存结构
- Head Block:当前正在写入的 block,驻留在内存
- WAL(Write-Ahead Log):持久化未写入磁盘的数据,防止崩溃丢失
八、数据模型总结表
| 特性 | 说明 |
|---|---|
| 模型类型 | 多维时间序列 |
| 唯一标识 | (metric name + labels) |
| 数据点 | (timestamp, value) 样本 |
| 标签作用 | 维度切片、聚合、过滤 |
| 核心类型 | Counter, Gauge, Histogram, Summary |
| 存储机制 | 本地 TSDB,按 block 存储 |
| 查询语言 | PromQL,支持多维操作 |
九、常见问题与最佳实践
❓ 为什么不能用 user_id 作为标签?
- 假设有 100 万用户 → 100 万个时间序列
- 每个序列都要维护内存结构、WAL、索引
- 导致:
- 内存爆炸(OOM)
- 查询变慢
- 抓取超时
✅ 正确做法:使用 user_count + tier="premium" 等低基数标签
❓ Histogram vs Summary 如何选择?
| 对比项 | Histogram | Summary |
|---|---|---|
| 是否支持聚合 | ✅ 跨实例可聚合 | ❌ 不支持 |
| 客户端开销 | 低(只需分桶) | 高(维护滑动窗口) |
| 灵活性 | 高(可在查询时计算任意分位数) | 低(固定 quantiles) |
| 推荐程度 | ✅ 强烈推荐 | ⚠️ 仅用于无法使用 Histogram 的场景 |
✅ 生产环境优先使用 Histogram
十、总结
Prometheus 的数据模型是其强大分析能力的基础:
“指标名称 + 标签 = 唯一时间序列”
通过合理设计指标名称和标签,你可以构建一个灵活、高效、可维护的监控体系。
黄金法则:
- ✅ 使用 低基数标签
- ✅ 优先使用 Histogram 而非 Summary
- ✅ 避免 高基数爆炸
- ✅ 统一 命名规范
- ✅ 利用 PromQL 进行多维分析
掌握 Prometheus 数据模型,是构建云原生可观测性系统的第一步,也是最关键的一步。
3万+

被折叠的 条评论
为什么被折叠?



