4、Prometheus核心概念:数据模型与指标类型

聊监控,绕不开 Prometheus。在特征平台里,它几乎就是标配。今天我把它的核心概念拆开揉碎了讲一遍。这些东西你搞懂了,后面搭建 SLA 监控面板才会顺手。

4.1 数据模型:Metric 与 Label

Prometheus 的数据模型,说白了就是一个带标签的时间序列。

时间序列是什么?就是同一指标在不同时间点的取值集合。每个时间序列由两部分组成:指标名(Metric) 和 标签(Label)。

举个例子:

feature_store_request_total{method="GET", endpoint="/api/v1/features", status="200"} 1024

这里 feature_store_request_total 是指标名,{method="GET", endpoint="/api/v1/features", status="200"} 是标签集合,1024 是当前值。

我个人习惯把标签分成两类:

  • 标识性标签:比如 instance、job,用来唯一确定监控目标
  • 维度标签:比如 method、status、endpoint,用来做聚合分析
经验之谈:标签的基数(Cardinality)一定要控制好。我曾经见过一个团队把 user_id 直接当标签,结果 Prometheus 内存直接爆了。标签值数量级超过 10 万,就要考虑用其他方案了。

你想想看,为什么 Prometheus 要设计成这种模型?因为它要支持灵活的聚合查询。你可以通过标签任意组合,从不同维度看数据。比如:

  • 只看 GET 请求的总数:sum(feature_store_request_total{method="GET"})
  • 按状态码分组:sum by(status) (feature_store_request_total)

4.2 四种指标类型

Prometheus 提供了四种指标类型。我刚开始接触时也觉得有点绕,但用多了就发现,每种类型都有它最合适的场景。

类型 特点 典型场景 注意事项
Counter 只增不减,重启归零 请求总数、错误总数 不能用来算当前值,要用 rate() 算速率
Gauge 可增可减,反映当前状态 CPU 使用率、内存占用、队列长度 直接取值即可,不需要 rate()
Histogram 分桶统计,可算分位数 请求延迟、响应大小 桶的区间要合理设置,否则浪费资源
Summary 客户端预计算分位数 延迟分位数(p99/p95) 分位数在客户端算,服务端无法聚合

4.2.1 Counter:只增不减的计数器

Counter 是最简单的类型。它只记录累计值,比如总请求数、总错误数。你没法直接用它看当前 QPS,得配合 rate() 或 increase() 函数。

# 定义 Counter
feature_store_request_total = Counter('feature_store_request_total', 'Total requests', ['method', 'endpoint', 'status'])

# 查询:过去 5 分钟的平均 QPS
rate(feature_store_request_total[5m])
注意:Counter 在进程重启后会归零。如果你用 increase() 函数,重启瞬间会出现一个负的增量。我建议用 rate() 代替 increase(),它对重启有更好的处理。

4.2.2 Gauge:可上可下的仪表盘

Gauge 反映的是当前值。比如内存使用量、在线连接数、队列深度。它不需要 rate(),直接取值就行。

# 定义 Gauge
feature_cache_memory_bytes = Gauge('feature_cache_memory_bytes', 'Current cache memory usage', ['cache_name'])

# 查询:当前缓存使用量
feature_cache_memory_bytes{cache_name="online"}

嗯,这里要注意:Gauge 虽然简单,但容易踩坑。我遇到过一个问题——Gauge 的更新频率太低,导致告警延迟。比如你每 60 秒才更新一次内存值,那内存突增时,告警可能要等 1 分钟才能触发。

4.2.3 Histogram:分桶统计的艺术

Histogram 是四种类型里最复杂的,也是最强大的。它把观测值放入预定义的桶(Bucket)里,然后统计每个桶的计数。

# 定义 Histogram,桶区间为 0.1, 0.5, 1.0, 2.5, 5.0, 10.0 秒
feature_request_duration_seconds = Histogram(
    'feature_request_duration_seconds',
    'Request latency in seconds',
    ['method', 'endpoint'],
    buckets=[0.1, 0.5, 1.0, 2.5, 5.0, 10.0]
)

用 Histogram 算 p99 延迟:

histogram_quantile(0.99, sum(rate(feature_request_duration_seconds_bucket[5m])) by (le))
避坑指南:桶的区间设置很关键。我曾经把桶设得太稀疏,结果 p99 算出来全是 10 秒,根本看不出问题。后来改成指数分布(0.01, 0.05, 0.1, 0.5, 1, 2.5, 5, 10),效果就好多了。

4.2.4 Summary:客户端预计算的分位数

Summary 和 Histogram 都能算分位数,但有个本质区别:Summary 在客户端就计算好了分位数,服务端直接拿结果。而 Histogram 只存桶计数,分位数在查询时计算。

# 定义 Summary,计算 p50、p90、p99
feature_request_duration_summary = Summary(
    'feature_request_duration_summary',
    'Request latency summary',
    ['method', 'endpoint'],
    quantiles=[0.5, 0.9, 0.99]
)

Summary 的好处是查询快,但坏处也很明显——你没法跨实例聚合分位数。比如你有 10 个实例,每个实例的 p99 是 1 秒,但全局 p99 可能是 5 秒。Summary 算不出来这个全局值。

我的建议:大多数场景用 Histogram。虽然查询时计算分位数有点慢,但灵活性高得多。只有当你对查询性能极其敏感,且不需要跨实例聚合时,才考虑 Summary。

4.3 Pull 模型与 Pushgateway

Prometheus 默认是 Pull 模型——它主动去拉取目标的数据。但有些场景下,目标没法被直接拉取,比如批处理任务、短生命周期任务。这时候就需要 Pushgateway 了。

4.3.1 Pull 模型:谁拉谁主动

Pull 模型的工作流程很简单:

  1. Prometheus Server 根据配置,定期访问目标的 /metrics 端点
  2. 目标返回当前所有指标数据
  3. Prometheus 存储并处理这些数据

Pull 模型的好处:

  • 你可以在 Prometheus 端控制采集频率,统一管理
  • 目标挂了,Prometheus 能立刻发现(采集超时)
  • 不需要在目标端安装额外的推送组件

但 Pull 模型也有局限。比如你有一个定时任务,跑 10 秒就结束了。Prometheus 还没来拉取,任务已经退出了。这时候就需要 Pushgateway。

4.3.2 Pushgateway:临时任务的救星

Pushgateway 是一个中间代理。任务把指标推送给 Pushgateway,Prometheus 再从 Pushgateway 拉取。

# 批处理任务结束时,推送指标到 Pushgateway
echo "feature_etl_duration_seconds 120.5" | curl --data-binary @- http://pushgateway:9091/metrics/job/feature_etl
注意:Pushgateway 不是万能的。它有个大坑——指标不会自动过期。如果某个任务挂了,它上次推送的指标会一直留在 Pushgateway 里。Prometheus 拉取时,会误以为任务还在运行。

我曾经踩过这个坑。一个 ETL 任务崩溃了,但 Pushgateway 里还留着它上次成功运行的指标。结果监控面板显示一切正常,直到用户反馈数据没更新,我们才发现问题。

解决方案:在任务启动时,先清理旧的指标,或者给指标加上时间戳,配合 max_over_time 函数做判断。

4.4 知识体系总览

下面这张图把本章的核心概念串起来了。你可以看到数据模型、指标类型、采集模型之间的关系。

Prometheus 核心概念知识体系 Prometheus 核心概念知识体系 数据模型 Metric(指标名) Label(标签) 四种指标类型 Counter Gauge Histogram Summary 采集模型 Pull 模型 Pushgateway 核心:时间序列 = Metric + Label,通过 Pull/Push 采集,用四种类型适配不同监控场景 Counter 算速率,Gauge 看当前,Histogram 做分桶,Summary 预计算

这张图把三个核心模块串起来了。数据模型是基础,指标类型是工具,采集模型是手段。三者配合,才能构建出完整的监控体系。

好了,这一章的内容就到这里。Prometheus 的数据模型和指标类型是后续所有监控工作的基石。你把这些概念吃透了,后面搭建 SLA 监控面板、配置告警规则,都会顺手很多。