首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Prometheus 监控越跑越胖?别急着加硬盘,TSDB 压缩才是关键

Prometheus 监控越跑越胖?别急着加硬盘,TSDB 压缩才是关键

原创
作者头像
Echo_Wish
发布2026-09-04 08:15:07
发布2026-09-04 08:15:07
20
举报

Prometheus 监控越跑越胖?别急着加硬盘,TSDB 压缩才是关键

文 / Echo_Wish

很多运维同学都有过这种经历:

刚搭好 Prometheus 的时候,感觉一切都挺美。

CPU、内存、磁盘、网络、容器、Pod……各种指标一股脑采进来。

磁盘?够大。

于是放心大胆地采。

结果几个月以后,服务器磁盘开始报警:

“磁盘空间不足。”

一查,好家伙。

Prometheus 自己就占了几十 GB,甚至上百 GB。

这时候很多人的第一反应是:

加硬盘。

硬盘确实能解决问题,但我觉得这其实是运维里一个非常典型的思维误区:

数据增长太快的时候,第一反应不应该是“存更多”,而应该是“为什么要存这么多”。

而这背后,就涉及 Prometheus 最核心的一个东西:

TSDB——Time Series Database,时序数据库。

今天我们就聊聊,时序数据库到底在监控系统里干什么,以及 Prometheus TSDB 到底是怎么通过压缩,让几十亿个监控数据点不至于把你的硬盘吃光。


一、监控系统为什么非得用时序数据库?

先想一个问题。

普通业务数据库,比如 MySQL,最擅长存什么?

比如:

代码语言:sql
复制
user_id = 10001
name = '张三'
age = 28

这类数据最大的特点是:

一条数据描述一个实体。

但是监控数据完全不一样。

比如我们监控服务器 CPU:

代码语言:text
复制
10:00:01  cpu_usage = 32%
10:00:02  cpu_usage = 35%
10:00:03  cpu_usage = 34%
10:00:04  cpu_usage = 36%
10:00:05  cpu_usage = 33%

你会发现:

时间是绝对核心。

而且监控数据还有一个非常明显的特点:

数据量巨大,但是单条数据的信息量非常小。

一台服务器可能几十个指标。

100 台服务器就是几千个时间序列。

到了 Kubernetes:

代码语言:text
复制
1000 Pods
×
几十个指标
×
多个 Label
×
每秒采集

数据量直接开始起飞。

所以监控系统真正需要解决的问题不是:

“怎么把一条数据存下来?”

而是:

“怎么高效地保存海量、连续、按时间增长的数据?”

这就是时序数据库存在的价值。


二、Prometheus 的 TSDB 到底是什么?

很多人使用 Prometheus,只知道:

代码语言:text
复制
Exporter
   ↓
Prometheus
   ↓
Grafana

但 Prometheus 中间其实还有一个非常重要的角色:

代码语言:text
复制
Exporter
    ↓
Prometheus
    ↓
TSDB
    ↓
磁盘

Prometheus 默认会把采集到的时间序列数据写入自己的 TSDB。

所谓 TSDB,可以简单理解成:

专门为“时间 + 数值 + 标签”设计的数据库。

例如:

代码语言:text
复制
http_requests_total{
    method="GET",
    status="200",
    service="user-service"
}

然后不断产生:

代码语言:text
复制
10:00:01 → 100
10:00:02 → 103
10:00:03 → 105
10:00:04 → 106

Prometheus 并不是简单地把这些数据一行一行塞进一个文件。

它会把数据组织成时间序列,并通过内存缓冲、WAL、Block 等机制,把数据最终持久化到磁盘。

大致可以理解成:

代码语言:text
复制
采集数据
   ↓
Head
   ↓
WAL
   ↓
Block
   ↓
压缩
   ↓
磁盘

其中最值得我们关注的,就是:

压缩。

因为监控数据有一个天然优势:

它特别适合压缩。


三、为什么监控数据特别适合压缩?

举个最简单的例子。

CPU 数据可能是:

代码语言:text
复制
31
32
32
33
33
34
34
34
35

如果你每次完整保存:

代码语言:text
复制
31
32
32
33
33
34
34
34
35

其实非常浪费。

因为相邻数据变化很小。

完全可以只保存:

代码语言:text
复制
31
+1
0
+1
0
+1
0
0
+1

这就是时序数据压缩的核心思想之一:

不要重复保存“变化不大的东西”。

Prometheus 的 TSDB 对样本值和时间戳都有专门的压缩思路。

尤其是浮点数数据,并不是简单地:

代码语言:text
复制
timestamp + value
timestamp + value
timestamp + value

全部原样写入。

而是尽可能利用相邻样本之间的规律。


四、时间戳其实也能压缩

比如 Prometheus 每 15 秒采集一次:

代码语言:text
复制
1000
1015
1030
1045
1060
1075

如果每个时间戳都完整保存:

代码语言:text
复制
1000
1015
1030
1045
1060
1075

其实没有必要。

因为我们已经知道:

代码语言:text
复制
每次 +15

于是可以把它理解成:

代码语言:text
复制
1000
+15
+15
+15
+15
+15

再配合进一步的编码方式,实际存储空间就能明显降低。

这就是为什么:

时序数据库和普通数据库的数据压缩逻辑,本身就不太一样。


五、Prometheus 真正容易“爆盘”的,其实不是数值

这里我要说一个很多初学者容易忽略的问题。

很多人认为:

“Prometheus 磁盘越来越大,是因为采集的数据太多。”

这句话没错。

但还不够准确。

真正容易把 Prometheus 搞崩的,往往是:

高基数(High Cardinality)

什么叫高基数?

例如:

代码语言:text
复制
http_requests_total{
    method="GET",
    status="200",
    user_id="100001"
}

如果:

代码语言:text
复制
user_id

有 100 万个。

那么理论上就可能产生:

代码语言:text
复制
100 万个时间序列

再乘:

代码语言:text
复制
method
×
status
×
service
×
pod

时间序列数量很快就上去了。

这时候你会发现:

真正吃资源的,不只是数据点,而是时间序列本身。


六、所以 Prometheus 优化,第一步不是压缩

很多人看到 TSDB 优化,第一反应:

“有没有什么参数可以让 Prometheus 压缩得更狠?”

我的观点是:

别急。

真正有效的优化顺序应该是:

代码语言:text
复制
降低无意义指标
      ↓
控制 Label
      ↓
降低高基数
      ↓
合理采集频率
      ↓
设置 Retention
      ↓
最后再考虑存储和压缩

为什么?

因为:

你压缩一个垃圾数据,不如一开始就别采。


七、第一招:千万别把用户 ID 当 Label

比如你的接口:

代码语言:text
复制
/api/order/100001
/api/order/100002
/api/order/100003

有些人为了方便统计,直接做:

代码语言:text
复制
http_request_total{
    path="/api/order/100001"
}

然后:

代码语言:text
复制
/api/order/100002

又变成另外一条时间序列。

这就麻烦了。

正确思路应该是:

代码语言:text
复制
/api/order/{id}

统一成:

代码语言:text
复制
http_request_total{
    path="/api/order/{id}"
}

这一个改动,有时候比你买几块 SSD 都管用。


八、第二招:控制采集频率

假设一个指标:

代码语言:text
复制
scrape_interval = 5s

一天的数据点数量:

代码语言:text
复制
24 × 60 × 60 ÷ 5

也就是:

代码语言:text
复制
17280

如果改成:

代码语言:text
复制
15s

一天:

代码语言:text
复制
5760

直接变成原来的三分之一。

如果你的业务并不需要秒级监控,那么:

为什么非要 5 秒采一次?

比如磁盘容量:

代码语言:text
复制
15s

通常完全够用。

而某些高实时性指标,可以:

代码语言:text
复制
5s

甚至:

代码语言:text
复制
1s

关键是:

不同指标应该有不同的采集策略,而不是全世界统一 15 秒。


九、第三招:Retention 比压缩更加简单粗暴

Prometheus 可以通过启动参数控制数据保留时间。

例如:

代码语言:bash
复制
prometheus \
  --storage.tsdb.retention.time=15d

意思就是:

数据保留 15 天。

如果你的监控数据只需要保存 15 天,就不要莫名其妙保存半年。

还有一种情况:

代码语言:text
复制
Prometheus
    ↓
只负责最近数据
    ↓
长期数据
    ↓
远端存储

比如结合:

代码语言:text
复制
Thanos
Cortex
Mimir
VictoriaMetrics

等方案,把 Prometheus 定位成:

实时监控 + 本地短期存储

长期数据交给专门的存储体系。

这其实是非常常见的架构。


十、Prometheus TSDB 的 Block 到底是什么?

Prometheus 的 TSDB 数据并不是永远躺在 Head 里。

随着时间推进,数据会被组织成一个个 Block。

可以简单理解:

代码语言:text
复制
Block 1
00:00 ───── 02:00

Block 2
02:00 ───── 04:00

Block 3
04:00 ───── 06:00

不同版本和配置下具体行为会有所差异,但从理解角度来说:

Block 就像把一段时间的数据打包成一个个“小仓库”。

一个 Block 里面包含索引、chunks 等数据结构。

例如:

代码语言:text
复制
01JXXXX/
├── chunks/
├── index
├── meta.json
└── tombstones

这样做的好处非常明显。

查询:

代码语言:text
复制
最近 1 小时

不需要把整个历史数据全部翻一遍。

只需要定位相关时间范围的数据。


十一、为什么删除数据不等于磁盘马上变小?

这是另一个非常容易踩坑的地方。

比如:

代码语言:bash
复制
promtool tsdb delete

或者通过其他方式删除数据。

你可能会发现:

“奇怪,我数据都删了,磁盘怎么没明显下降?”

原因之一就是:

删除和物理回收不是一回事。

TSDB 会涉及 Block、tombstone、compaction 等机制。

简单理解:

代码语言:text
复制
逻辑删除
   ↓
标记删除
   ↓
Compaction
   ↓
重新整理 Block
   ↓
旧数据真正释放

所以看到磁盘没有马上下降,不一定代表删除失败。


十二、Compaction 到底是在干什么?

可以把 Compaction 理解成:

把很多零零散散的数据仓库重新整理。

比如:

代码语言:text
复制
Block A
Block B
Block C
Block D

里面存在大量重复结构。

Compaction 会重新组织:

代码语言:text
复制
Block A+B+C+D
        ↓
   新 Block

这样可以:

  • 减少冗余
  • 优化存储
  • 提高查询效率
  • 清理已经删除的数据

所以:

Compaction 是 TSDB 非常核心的一环。


十三、Prometheus 优化到底应该怎么做?

如果让我给一个线上 Prometheus 做优化,我一般会先看这几个东西。

1. 看时间序列数量

代码语言:promql
复制
prometheus_tsdb_head_series

这个指标非常值得关注。

如果:

代码语言:text
复制
100 万
→
200 万
→
500 万

持续增长。

那就要警惕了。


2. 看存储增长速度

例如:

代码语言:promql
复制
rate(prometheus_tsdb_storage_blocks_bytes[1h])

结合实际版本提供的 TSDB 指标进行观察。

重点不是盯着某一个数字,而是:

看趋势。

如果每天:

代码语言:text
复制
+2GB
+2GB
+2GB

那一个月就是:

代码语言:text
复制
60GB

三个月:

代码语言:text
复制
180GB

这才是运维真正应该关心的东西。


十四、别迷信“压缩率”,指标治理才是核心

我特别想强调一个观点:

Prometheus TSDB 的压缩很重要,但它不是万能药。

如果你的系统:

代码语言:text
复制
10 万时间序列

突然变成:

代码语言:text
复制
1000 万时间序列

你再好的压缩算法,也救不了你。

这就像:

房间里已经堆满垃圾了,你研究垃圾袋的压缩技术,不如先把垃圾扔掉。

所以 Prometheus 优化最核心的逻辑,其实可以总结成一句话:

先控制数据产生,再优化数据存储。


十五、生产环境我更推荐这套思路

如果是一个 Kubernetes 集群,我比较推荐这样的监控架构:

代码语言:text
复制
             Kubernetes
                  │
        ┌─────────┴─────────┐
        ↓                   ↓
    Node Exporter       kube-state-metrics
        │                   │
        └─────────┬─────────┘
                  ↓
              Prometheus
                  │
        ┌─────────┴─────────┐
        ↓                   ↓
     本地 TSDB          Remote Write
        │                   │
   最近 7~15 天       长期时序存储
                            │
                   ┌────────┴────────┐
                   ↓                 ↓
                Thanos            Mimir

Prometheus 本地负责:

快。

远端存储负责:

久。

Grafana 负责:

好看。

Alertmanager 负责:

报警。

每个组件各干各的活,整个系统反而更稳。


十六、最后聊点我的真实感受

做运维久了,你会发现一个很有意思的现象:

监控系统最容易犯的错误,就是“什么都想监控”。

CPU 要监控。

内存要监控。

磁盘要监控。

Pod 要监控。

接口要监控。

用户要监控。

订单要监控。

甚至有人恨不得把业务代码里的每个变量都做成 Metric。

最后 Grafana 上几百个 Dashboard,Prometheus 里面几百万甚至上千万条时间序列。

但真正发生故障的时候:

没人知道该看哪个。

所以我越来越觉得:

好的监控,不是采集的数据越多越好,而是关键问题能够被快速发现。

TSDB 压缩解决的是:

“这么多数据怎么存?”

而监控治理解决的是:

“这些数据到底有没有必要存?”

这两个问题看起来很像,其实完全不是一个层面。


写在最后

如果你现在的 Prometheus 已经开始出现:

代码语言:text
复制
磁盘不断增长
TSDB 占用越来越高
内存越来越大
查询越来越慢
Kubernetes Pod 数量一多就开始卡

别第一时间想着:

“给 Prometheus 加 CPU、加内存、加硬盘。”

先去看看:

代码语言:text
复制
到底有多少 Time Series?

再看看:

代码语言:text
复制
哪些 Label 基数特别高?

然后检查:

代码语言:text
复制
scrape_interval 是否合理?
Retention 是否合理?
有没有大量无意义指标?
是否应该引入 Remote Storage?

很多时候,真正的优化并不是把 Prometheus 变得更强。

而是:

让它少干一点没意义的活。

这才是时序数据库优化里,我认为最接地气、也最容易被忽略的一条经验。

监控不是“存得越多越专业”,而是“关键的数据,恰好被你留下来了”。

—— Echo_Wish

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • Prometheus 监控越跑越胖?别急着加硬盘,TSDB 压缩才是关键
    • 一、监控系统为什么非得用时序数据库?
  • 二、Prometheus 的 TSDB 到底是什么?
  • 三、为什么监控数据特别适合压缩?
  • 四、时间戳其实也能压缩
  • 五、Prometheus 真正容易“爆盘”的,其实不是数值
  • 高基数(High Cardinality)
  • 六、所以 Prometheus 优化,第一步不是压缩
  • 七、第一招:千万别把用户 ID 当 Label
  • 八、第二招:控制采集频率
  • 九、第三招:Retention 比压缩更加简单粗暴
  • 十、Prometheus TSDB 的 Block 到底是什么?
  • 十一、为什么删除数据不等于磁盘马上变小?
  • 十二、Compaction 到底是在干什么?
  • 十三、Prometheus 优化到底应该怎么做?
    • 1. 看时间序列数量
    • 2. 看存储增长速度
  • 十四、别迷信“压缩率”,指标治理才是核心
  • 先控制数据产生,再优化数据存储。
  • 十五、生产环境我更推荐这套思路
  • 十六、最后聊点我的真实感受
    • 写在最后
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档