什么是 Prometheus
必要,但同样概念级加会读即可。告警规则、PromQL、抓取配置可让 AI 生成,但「什么该做成指标、基数爆炸为何会打崩集群、告警阈值怎么定」需要你真正懂时序监控的边界,否则 AI 配的规则只会制造噪声或漏报。建议目标:理解时序数据模型、Pull 模型与标签基数的坑,能读懂仪表盘并判断指标设计是否合理。
Prometheus 是一个开源的监控系统 + 时序数据库(TSDB),2012 年诞生于 SoundCloud,2016 年成为 CNCF 继 Kubernetes 之后的第二个毕业项目。今天它几乎是云原生世界里指标监控的事实标准。
一句话概括它的工作方式:周期性地去目标服务的 HTTP 接口把指标「拉」回来,存进本地时序数据库,然后用 PromQL 查询、画图和告警。
Prometheus 是可观测性三大支柱里 Metrics(指标) 那一根柱子。它不存日志(那是 Loki / ELK 的事),也不存链路(那是 Tempo / Jaeger 的事)。想清楚这个边界,能省掉很多「为什么 Prometheus 查不到我的日志」的困惑。
1. 为什么监控需要专门的时序数据库
新手常问:监控数据存 MySQL 不行吗?技术上行,实践上灾难。因为监控数据的形态和业务数据完全不同。
假设你有 500 台机器,每台采集 200 个指标,每 15 秒一次:
500 台 × 200 指标 × (60 / 15) 次/分 = 400,000 个数据点/分钟
≈ 5.76 亿个数据点/天这类数据有四个鲜明特征:
| 特征 | 说明 | 对存储的要求 |
|---|---|---|
| 写多读少 | 持续高频写入,查询只在排查/看板时发生 | 写入路径必须极轻量 |
| 只追加 | 几乎从不 UPDATE / DELETE 单条记录 | 不需要复杂的事务与行级锁 |
| 按时间访问 | 查询永远带时间范围(最近 1h、昨天同期) | 按时间分块存储,快速裁剪 |
| 数值高度相似 | 相邻样本值接近、时间戳等差 | 可做极致压缩 |
关系型数据库为「随机读写 + 事务 + 强一致」优化,付出的是每行几十字节的存储与索引开销。而时序数据库利用上述特征做了针对性设计:
- 差分 + 变长编码(Gorilla 压缩):时间戳存差值的差值,浮点值存 XOR 后的有效位。Prometheus 实测平均每个样本只占 1–2 字节,而在 MySQL 里同样一条记录轻松超过 50 字节。
- 按时间分块(block):默认每 2 小时一个块,查「最近 1 小时」只需读最新的块,老数据整块删除即可过期。
- 倒排索引找序列:先用标签索引定位到「哪些时间序列」,再在这些序列里按时间扫描,避免全表扫描。
按 1.5 字节/样本估算,上面例子的 5.76 亿点/天只占约 0.8 GB/天。同样的数据塞进 MySQL(含索引)大概率要 30 GB 以上,还查不动。这就是为什么监控要用专门的 TSDB。
2. Pull vs Push:Prometheus 的 Pull 哲学
大多数传统监控(Zabbix Agent 主动模式、StatsD、Graphite)是 Push 模型:被监控方主动把数据推给服务端。Prometheus 反其道而行,采用 Pull(拉取)模型:
Push 模型: 应用 ──推送──▶ 监控服务端
Pull 模型: 监控服务端 ──HTTP GET /metrics──▶ 应用Prometheus 会按配置的间隔(默认 15s)去访问每个目标的 /metrics 接口,把返回的文本解析成样本存起来。这个动作叫 scrape(抓取)。
Pull 的优点
-
目标存活天然可观测:抓不到就说明目标挂了。Prometheus 会自动为每个目标生成一个
up指标(1 = 抓取成功,0 = 失败),你几乎不用额外写探活逻辑。Push 模型下「没收到数据」有歧义——是服务挂了,还是网络断了,还是它本来就不发? -
配置集中在服务端:谁被监控、多久抓一次,全部写在 Prometheus 的配置文件里。上千个应用不需要每个都配一遍服务端地址。
-
可手动调试:任何时候你都能自己
curl一下目标接口,看到和 Prometheus 完全一样的数据。这对排查「指标为什么不对」极其友好。# 你看到的,就是 Prometheus 看到的 curl -s http://10.0.0.12:9100/metrics | head -20 -
不会被打垮:抓取速率由服务端控制。Push 模型下,一次流量洪峰可能让上万实例同时猛推数据,把监控系统冲垮——而监控系统恰恰应该在故障时最稳。
-
易于做多副本 / 分层:跑两个配置相同的 Prometheus 就得到了高可用,它们各自去拉,互不干扰。
Pull 的局限
Pull 不是银弹,它有几个明确的短板:
- 短生命周期任务:一个跑 3 秒就结束的 CronJob,Prometheus 根本来不及抓。这类场景需要 Pushgateway 中转(第 2 章详述)。
- 网络可达性要求:Prometheus 必须能主动连到每个目标。目标在 NAT 后面、在客户端设备上、跨越严格防火墙时,Pull 就很别扭。
- 事件类数据不适合:Pull 拿到的是「此刻的状态快照」。两次抓取之间发生的瞬时尖峰会被抹平,单次业务事件(一笔订单)也不该用指标来记——那是日志/数仓的活。
Pull 与 Push 的争论常被过度神化。真实工程里 Prometheus 生态两者都用:绝大多数场景 Pull,短任务用 Pushgateway,超大规模跨机房用 remote_write(本质是 Push 到长期存储)。选型看场景,不看教条。
3. 核心概念:时序、样本、标签、指标名
这四个词会贯穿整个教程,先建立准确的直觉。看一行真实的 /metrics 输出:
http_requests_total{job="api", method="GET", status="200"} 1342- 指标名(metric name):
http_requests_total。回答「测的是什么」。 - 标签(label):
job="api"、method="GET"、status="200"。回答「是哪一维度的」,是一组键值对。 - 时序(time series):指标名 + 一组标签唯一确定一条时间序列。上面这行就属于一条特定的序列。只要有任何一个标签的值不同(比如
status="500"),那就是另一条独立的序列。 - 样本(sample):这条序列在某个时刻的一个数据点,形如
(时间戳, 值)。值永远是 float64,时间戳精确到毫秒。
用一张图理解它们的层级关系:
指标名 http_requests_total
├── 序列 A: {method="GET", status="200"}
│ └── 样本: (10:00:00, 1342) (10:00:15, 1360) (10:00:30, 1389) ...
├── 序列 B: {method="GET", status="500"}
│ └── 样本: (10:00:00, 3) (10:00:15, 3) (10:00:30, 7) ...
└── 序列 C: {method="POST", status="200"}
└── 样本: (10:00:00, 221) (10:00:15, 230) (10:00:30, 244) ...有了标签,查询就变成了「多维切片」。在 PromQL 里:
# 全部序列
http_requests_total
# 只要 500 的那条
http_requests_total{status="500"}
# 按 method 维度聚合出每秒请求数
sum by (method) (rate(http_requests_total[5m]))每多一个标签取值组合,就多一条独立时间序列,这叫基数(cardinality)。给指标打上 user_id 或 request_id 这类标签,会瞬间制造上百万条序列,直接把 Prometheus 内存打爆。标签值必须是有限且低基数的集合。第 4 章会专门展开。
4. 与其他方案的粗线条对比
| 维度 | Prometheus | Zabbix | InfluxDB | 商业 APM(Datadog / New Relic) |
|---|---|---|---|---|
| 定位 | 云原生指标监控 | 传统主机/网络监控 | 通用时序数据库 | 一站式可观测性 SaaS |
| 数据模型 | 指标名 + 多维标签 | 主机 + Item(层级式) | measurement + tag + field | 指标 + 标签(类似 Prom) |
| 采集方式 | Pull 为主 | Agent Push / Server Pull 皆可 | 主要 Push(Telegraf) | Agent Push |
| 查询语言 | PromQL(专为指标设计) | 触发器表达式(较弱) | InfluxQL / Flux | 各家私有 |
| 服务发现 | 原生支持 K8s / Consul / 云厂商 | 需自动注册,较繁琐 | 无,靠采集端 | Agent 自动发现 |
| 告警 | 内置规则 + Alertmanager | 内置,功能完备 | 需搭配 Kapacitor | 内置,开箱即用 |
| 长期存储 | 本地盘为主,长期需 Thanos/Mimir | 依赖 MySQL/PG | 自带(含集群版,商业) | SaaS 托管 |
| 成本 | 免费,但要自己运维 | 免费,运维成本中 | 开源版单机 | 按主机/数据量计费,昂贵 |
几句大白话总结:
- Zabbix 强在传统 IDC:网络设备 SNMP、硬件告警、开箱即用的模板库。但它的数据模型是「主机 → 监控项」的树形结构,面对「一个服务 50 个动态 Pod」这种云原生场景会非常吃力。
- InfluxDB 是通用 TSDB,更适合 IoT 传感器、业务埋点这类需要写入任意时序数据的场景,也支持字符串等非数值类型。但它自己不做服务发现和抓取,需要 Telegraf 配合;开源版还没有高可用。
- 商业 APM 胜在省心:装个 Agent,指标、日志、链路、代码级火焰图全都有。代价是账单——按主机数或指标基数计费,规模上来后一年几十万人民币很常见,且数据在别人手里。
- Prometheus 的甜点区是云原生动态环境:容器随时起停、IP 随时变化,靠服务发现自动跟上;多维标签 + PromQL 能回答任意切片的问题。代价是你要自己搞定高可用与长期存储。
5. 什么时候该用,什么时候不该
适合用 Prometheus
- Kubernetes / 容器化环境:几乎是标配,服务发现能力天生契合。
- 微服务的黄金指标监控:QPS、延迟、错误率、饱和度(RED / USE 方法)。
- 主机与中间件监控:node_exporter、mysqld_exporter、redis_exporter 等生态极其丰富,装上即用。
- 需要灵活多维分析:「北京机房 v2 版本的 POST 接口 5xx 率」这类问题,PromQL 一行就能回答。
- 希望告警规则纳入 Git 管理:规则就是 YAML 文件,天然可 Code Review、可版本化。
不适合用 Prometheus
- 需要 100% 精确的计费/审计数据。Prometheus 为可用性牺牲了准确性:抓取可能丢失、可能被采样、重启可能丢一小段 WAL。它是一个「足够准确」的系统,不是账本。 计费请走消息队列 + 数据库。
- 单个事件的明细追溯。想查「订单 #12345 到底发生了什么」,那是日志和链路的活。指标只有聚合后的数值。
- 高基数标签场景。用户 ID、会话 ID、URL 全路径、邮箱……这些进标签必炸。
- 超长期存储需求。原生 Prometheus 默认保留 15 天,设计上就是为短期高频查询服务。要存一年,得上 Thanos、Mimir 或 VictoriaMetrics。
- 日志检索。反复强调一次:Prometheus 不是日志系统。
- 非数值型数据。样本值只能是 float64,存不了字符串状态。变通做法是把状态编码进标签,值恒为 1(这种叫 info 指标)。
问自己两个问题:① 这个数据我关心的是趋势和聚合,还是每一条明细?② 它的维度组合是几十个,还是无上限?
只有「关心趋势 + 维度可控」的数据,才该进 Prometheus。
下面 5 类数据,判断哪些适合作为 Prometheus 指标采集,哪些不适合,并说明理由:
- 每台服务器的 CPU 使用率
- 每笔支付订单的金额与订单号
- 接口
/api/order按 HTTP 状态码分类的请求数 - 用户登录时的完整 User-Agent 字符串
- Redis 当前连接数
用你自己的话回答:
- 为什么说 Pull 模型让「目标存活」变得天然可观测?Push 模型下同样的判断难在哪?
- 举一个 Pull 模型明显不好用的场景,并说明 Prometheus 生态如何补救。
某服务暴露了指标 http_requests_total,带三个标签:
method:GET、POST、PUT、DELETE(4 种)status:200、400、404、500(4 种)instance:部署了 6 个实例
问:
- 理论上最多会产生多少条时间序列?
- 如果为了排查问题,再加一个
user_id标签(日活 10 万用户),序列数会变成多少?这会带来什么后果?
以下三个场景,分别推荐 Prometheus / Zabbix / 商业 APM 中的哪一个(或组合),说明理由:
- 一家创业公司,8 人研发团队,全部服务跑在 K8s 上,没有专职运维。
- 一家传统制造企业的机房,有 200 台物理服务器、大量交换机和 UPS 设备,需要监控硬件温度、风扇转速、SNMP 网络流量。
- 一个金融系统,需要精确到每一笔交易的耗时明细,用于事后审计与客诉举证。
小结
- Prometheus = 时序数据库 + 采集器 + 查询语言 + 告警引擎,专注 Metrics 这一支柱。
- 监控数据「写多读少、只追加、按时间访问」,所以需要专门的 TSDB;Gorilla 压缩让每个样本只占 1–2 字节。
- Pull 模型带来目标存活可观测、配置集中、易调试、不易被打垮;短任务和网络不可达是它的短板,用 Pushgateway 和 remote_write 补救。
- 核心概念:时序 = 指标名 + 标签集合,样本 = (时间戳, float64 值)。
- 甜点区是云原生动态环境;不要用它做计费、审计、日志检索和高基数分析。
- 下一章我们拆开 Prometheus 的架构,看看 Server、Exporter、Alertmanager 各自在干什么 →