2. Prometheus 核心概念:Pull模型、时间序列数据库、Metric类型、PromQL入门
好,咱们进入正题。这一章我打算把Prometheus最核心的几个概念掰开揉碎了讲清楚。你可能会觉得概念很枯燥,但相信我,搞懂了这些,后面搭建系统就跟玩似的。
2.1 Pull模型:为什么Prometheus要主动拉数据?
Prometheus最鲜明的特点,就是它的数据采集方式——Pull模型。说白了,就是Prometheus Server主动去各个目标机器上“拉”数据,而不是等着目标机器把数据“推”过来。
我刚开始接触时也觉得奇怪:为什么不用更常见的Push方式?后来在生产环境踩过坑才明白,Pull模型有几个天然优势:
- 可控性更强:Prometheus自己决定拉取频率和时机,不会被客户端的突发流量冲垮。
- 健康检测更简单:如果某个目标拉不到数据,基本可以判定它挂了。
- 配置即发现:你只需要告诉Prometheus“去这些地址拉数据”,它自己会搞定。
当然,Pull模型也有短板。比如在动态环境里,服务实例频繁启停,Prometheus怎么知道该去拉谁?这就引出了服务发现机制,咱们后面会专门讲。
2.2 时间序列数据库:数据是怎么存的?
Prometheus的存储引擎,本质上是一个时间序列数据库。什么叫时间序列?就是每个指标都带着时间戳和标签,按时间顺序排列。
举个例子,你监控一台服务器的CPU使用率:
node_cpu_seconds_total{cpu="0", mode="user"} 12345.67
node_cpu_seconds_total{cpu="0", mode="system"} 2345.67
这里node_cpu_seconds_total是指标名,{cpu="0", mode="user"}是标签,12345.67是值。每次采集都会生成一个新样本,带上当前时间戳。
我个人的习惯是,把时间序列数据库想象成一个巨大的Excel表格:
- 每一行是一个时间点的数据
- 每一列是一个唯一的指标组合(指标名+标签)
- 行数随时间无限增长
你想想看,如果所有数据都存着,磁盘迟早会爆。所以Prometheus有自己的压缩和过期策略。默认情况下,它会保留15天的数据,然后自动清理旧数据。
--storage.tsdb.retention.time 参数。
2.3 Metric类型:四种核心类型
Prometheus的指标类型,说白了就是四种:Counter、Gauge、Histogram、Summary。每种类型都有它的脾气,用错了会出笑话。
2.3.1 Counter:只增不减的计数器
Counter代表一个只增不减的数值。比如请求总数、错误总数、CPU时间片数。它最典型的用法是:
- 统计HTTP请求总量
- 统计数据库查询次数
- 统计任务执行次数
你可能会问:如果服务重启了,Counter会归零吗?会的。所以用Counter算增长率时,要小心重启带来的跳变。我一般会用rate()函数来平滑处理。
# 计算每秒请求增长率
rate(http_requests_total[5m])
2.3.2 Gauge:可增可减的仪表盘
Gauge代表一个可以上下波动的数值。比如内存使用量、CPU温度、在线用户数。它没有“只增不减”的限制,想怎么变就怎么变。
我记得有一次排查内存泄漏问题,就是用Gauge类型的process_resident_memory_bytes指标,配合delta()函数,一眼就看出了内存持续增长的趋势。
# 查看内存变化量
delta(process_resident_memory_bytes[1h])
2.3.3 Histogram:分布统计的利器
Histogram用于统计数据的分布情况。比如:
- 90%的请求在多少毫秒内完成?
- 大部分请求的响应时间集中在哪个区间?
它会把数据分到不同的桶(bucket)里。比如你定义桶为{0.1, 0.5, 1, 5}秒,那么Histogram会统计出:
- 响应时间 ≤ 0.1秒的请求有多少
- 响应时间 ≤ 0.5秒的请求有多少
- 以此类推
用Histogram算P99延迟,是监控里的经典操作:
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
2.3.4 Summary:自带分位数的统计
Summary和Histogram类似,但它直接在客户端算好了分位数。比如你配置了0.5、0.9、0.99分位数,Summary会直接暴露这些值。
它的好处是查询简单,不用写复杂的PromQL。但缺点也很明显:分位数是固定的,不能事后调整。而Histogram可以灵活查询任意分位数。
我个人更倾向于用Histogram,因为灵活性更高。除非你明确知道需要哪些分位数,并且不想在查询时增加计算负担。
2.4 PromQL入门:查询语言其实没那么难
PromQL是Prometheus的查询语言,说白了就是用来从时间序列数据库里捞数据的。刚开始看可能觉得像天书,但掌握几个核心函数后,你会发现它其实很直观。
2.4.1 最简单的查询:直接查指标
node_memory_MemTotal_bytes
这条语句会返回所有节点的总内存。如果有多台机器,你会看到多条时间序列。
2.4.2 加标签过滤:精确锁定目标
node_memory_MemTotal_bytes{instance="192.168.1.1:9100"}
用花括号加标签过滤,只查特定实例的数据。标签支持精确匹配(=)、正则匹配(=~)、反向匹配(!=)。
2.4.3 范围查询:看一段时间内的数据
node_memory_MemTotal_bytes[5m]
加上[5m],表示查询过去5分钟内的所有样本点。返回的是一个数组,而不是单个值。
2.4.4 常用函数:让数据说话
| 函数 | 作用 | 示例 |
|---|---|---|
rate() |
计算Counter的每秒增长率 | rate(http_requests_total[5m]) |
irate() |
计算瞬时增长率(更敏感) | irate(http_requests_total[5m]) |
avg() |
计算平均值 | avg(node_cpu_seconds_total) |
sum() |
求和 | sum(node_memory_MemTotal_bytes) |
topk() |
取前N个最大值 | topk(3, node_memory_MemFree_bytes) |
举个例子,你想看所有机器的CPU使用率:
100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100)
这条语句的意思是:先算出每台机器的空闲CPU占比,然后用100减去它,得到使用率。嗯,看着复杂,但拆开来看,每一步都很清晰。
2.5 本章小结
这一章我们聊了Prometheus的四个核心概念:
- Pull模型:主动拉取,可控性强
- 时间序列数据库:指标+标签+时间戳,按时间存储
- 四种Metric类型:Counter、Gauge、Histogram、Summary,各有各的用途
- PromQL入门:从简单查询到组合函数,一步步掌握
下一章,我会带你亲手搭建一个Prometheus实例,把今天学的概念都用起来。到时候你会发现,理论结合实践,才是最快的成长方式。