度量指标(Metrics)是可观测性三大支柱里最”省钱”也最成熟的一支。一条时间序列每秒写入一个浮点数,存储成本远低于日志,查询聚合也比分布式追踪简单得多。但当你的业务从几十台服务器扩张到几千个微服务,Prometheus
单实例的瓶颈就开始暴露:两周数据留存上限、单机内存压力、跨集群查询不通。本文从
Prometheus
的内部架构讲起,逐层拆解各主流扩展方案的工程取舍。
一、Prometheus
架构与数据模型
1.1 整体架构
普罗米修斯(Prometheus)由 SoundCloud 工程师 Matt T.
Proud 和 Julius Volz 于 2012 年开始设计,2016
年成为云原生计算基金会(CNCF)第二个孵化项目。其核心架构遵循”拉取(Pull)优于推送(Push)“的设计哲学。
┌──────────────────────────────────┐
│ Prometheus Server │
┌──────────┐ │ ┌──────────┐ ┌──────────────┐ │ ┌─────────────────┐
│ Target │◄─┼──│ Scrape │ │ TSDB │ │ │ Alertmanager │
│ /metrics │ │ │ Engine │─►│ WAL+Blocks │ │ │ (Alert Route) │
└──────────┘ │ └──────────┘ └──────┬───────┘ │ └─────────────────┘
┌──────────┐ │ ┌──────────┐ │ │
│ Target │◄─┼──│ SD │ │ │ ┌─────────────────┐
│ /metrics │ │ │ (K8s/ │ ┌──────▼───────┐ │ │ Grafana / │
└──────────┘ │ │ Consul) │ │ PromQL │◄─┼──│ HTTP API │
┌──────────┐ │ └──────────┘ │ Query Layer │ │ └─────────────────┘
│ Pushgate │──┼────────────────►└──────────────┘ │
│ way │ │ │
└──────────┘ └──────────────────────────────────┘
关键组件:
Scrape Engine :按
scrape_interval(默认 15s)主动拉取目标的
/metrics 端点,解析 Exposition 格式文本或
OpenMetrics Protobuf。
服务发现(Service Discovery,SD) :通过
kubernetes_sd_configs、consul_sd_configs
等动态发现抓取目标,避免手工维护 IP 列表。
TSDB :基于 WAL + 两小时内存块 +
本地磁盘块的混合存储,详见第七篇。
Pushgateway :为短生命周期 Job(如 Cron
任务)提供临时推送端点;不适用于持久指标。
Alertmanager :独立进程,接收 Prometheus
推送的告警,执行分组、抑制、路由、静默,再分发到 PagerDuty /
钉钉 / 飞书等渠道。
1.2 数据模型
普罗米修斯采用多维度时间序列(Multi-dimensional Time
Series)模型。每条序列由指标名(metric
name) 与标签集(label
set) 唯一标识:
http_requests_total{method="GET", status="200", handler="/api/v1/user"}
四种指标类型:
类型
语义
场景
Counter(计数器)
单调递增,仅在重启时重置
请求总数、错误总数
Gauge(仪表盘)
可任意升降
内存使用量、队列长度
Histogram(直方图)
观测值分桶计数,附
_sum/_count
请求延迟分布、请求大小
Summary(摘要)
客户端计算分位数(φ-quantile)
与 Histogram 类似,但分位数在客户端固定
Exposition 格式示例:
# HELP http_request_duration_seconds HTTP request latency histogram
# TYPE http_request_duration_seconds histogram
http_request_duration_seconds_bucket{le="0.05"} 24054
http_request_duration_seconds_bucket{le="0.1"} 33444
http_request_duration_seconds_bucket{le="0.2"} 100392
http_request_duration_seconds_bucket{le="0.5"} 129389
http_request_duration_seconds_bucket{le="1.0"} 133988
http_request_duration_seconds_bucket{le="+Inf"} 144320
http_request_duration_seconds_sum 53423
http_request_duration_seconds_count 144320
1.3 WAL 与 TSDB 写入路径
数据写入流程:
Scrape → 内存追加器(Append)→ WAL(Write-Ahead Log)→ 内存 Head Block(~2h)
↓ flush
磁盘只读 Block(2h 窗口)
↓ compaction
合并 Block(6h / 24h / 1w)
WAL :每次追加先写日志(mmap
文件),防止进程崩溃丢数据。WAL 段文件默认 128
MiB,超过则滚动。
Head
Block :当前两小时的数据保存在内存,超过后刷为只读磁盘块(chunks_head
→ block)。
压缩(Compaction) :后台将小块合并为更大时间窗口的块,同时删除过期数据(--storage.tsdb.retention.time)。
1.4 服务发现配置示例
Kubernetes Pod 服务发现:
scrape_configs :
- job_name : "kubernetes-pods"
kubernetes_sd_configs :
- role : pod
namespaces :
names : [ "default" , "production" ]
relabel_configs :
# 只抓有注解 prometheus.io/scrape: "true" 的 Pod
- source_labels : [ __meta_kubernetes_pod_annotation_prometheus_io_scrape ]
action : keep
regex : "true"
# 动态 port
- source_labels : [ __meta_kubernetes_pod_annotation_prometheus_io_port ]
action : replace
target_label : __address__
regex : (.+)
replacement : ${1}
# 保留 namespace、pod 名为标签
- source_labels : [ __meta_kubernetes_namespace ]
target_label : namespace
- source_labels : [ __meta_kubernetes_pod_name ]
target_label : pod
国内 Nacos 服务发现(通过 Prometheus 社区扩展):
# 使用 prometheus-nacos-sd(第三方 sidecar)将 Nacos 实例列表转为 file_sd JSON
scrape_configs :
- job_name : "nacos-services"
file_sd_configs :
- files :
- /etc/prometheus/sd/nacos/*.json
refresh_interval : 30s
relabel_configs :
- source_labels : [ __meta_nacos_service ]
target_label : service
- source_labels : [ __meta_nacos_cluster ]
target_label : cluster
二、Remote Write 协议
2.1 协议概述
远程写(Remote Write)是 Prometheus
将样本实时复制到外部存储的标准接口。协议使用 Protobuf +
Snappy 压缩,经 HTTP POST 发送到远端接收器。
Prometheus --[remote_write]--> VictoriaMetrics / Thanos Receive / Mimir / M3
配置示例:
remote_write :
- url : "http://victoriametrics:8428/api/v1/write"
remote_timeout : 30s
queue_config :
capacity : 10000
max_shards : 50
min_shards : 1
max_samples_per_send : 5000
batch_send_deadline : 5s
min_backoff : 30ms
max_backoff : 5s
write_relabel_configs :
# 只转发生产命名空间的指标
- source_labels : [ namespace ]
action : keep
regex : "production|staging"
2.2 Remote Write 2.0
Prometheus 2.54 引入 Remote Write
2.0(实验性),改进:
使用新 Protobuf 格式减少序列化开销。
支持元数据(metadata)内联传输。
引入 created_timestamp
字段,精准标记计数器重置。
2.3 背压(Back
Pressure)机制
Remote Write 使用分片队列(sharded
queue)缓冲待发送样本。当远端慢或宕机时:
样本写入内存队列
↓
队列满 → 丢样本(失败计数 prometheus_remote_storage_samples_failed_total++)
↓
监控队列深度:prometheus_remote_storage_queue_highest_sent_timestamp_seconds
关键监控指标:
# 检查队列积压(正常应 ≈ 0)
prometheus_remote_storage_pending_samples{job="prometheus"}
# 丢样本率(应为 0)
rate(prometheus_remote_storage_samples_failed_total[5m])
# 发送延迟
prometheus_remote_storage_highest_timestamp_in_seconds
- prometheus_remote_storage_queue_highest_sent_timestamp_seconds
三、PromQL 入门与进阶
3.1 基础查询
即时向量(Instant Vector)返回当前值:
# 所有 HTTP 请求的计数
http_requests_total
# 标签过滤
http_requests_total{status=~"5.."}
# 否定过滤
http_requests_total{environment!="dev"}
区间向量(Range Vector)返回时间窗口内的样本:
# 过去 5 分钟的样本
http_requests_total[5m]
3.2 速率函数
# 每秒请求速率(Counter 专用,处理 Reset)
rate(http_requests_total[5m])
# 瞬时变化(适合短窗口,但对 Counter Reset 不友好)
irate(http_requests_total[5m])
# increase:区间内增量(rate × interval 的近似)
increase(http_requests_total[1h])
rate vs irate
的选择:rate
对长窗口更平滑,适合告警;irate
对短尖刺更敏感,适合仪表盘。
3.3 Histogram 分位数
# p99 请求延迟(Histogram 要求 le 桶存在)
histogram_quantile(0.99,
sum by (le, service) (
rate(http_request_duration_seconds_bucket[5m])
)
)
# p50 / p95 / p99 并列
histogram_quantile(0.50, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
注意:跨序列 Histogram 相加后再调用
histogram_quantile
才有意义 ,不能先算分位数再相加。
3.4 Recording Rules
记录规则(Recording
Rules)把开销大的查询预计算为新的指标序列,提升仪表盘性能:
groups :
- name : http_metrics
interval : 60s
rules :
# 每分钟预计算 p99 延迟,按 service 聚合
- record : job:http_request_duration_p99:rate5m
expr : |
histogram_quantile(0.99,
sum by (le, job) (
rate(http_request_duration_seconds_bucket[5m])
)
)
# 预计算 QPS
- record : job:http_requests:rate5m
expr : |
sum by (job, status) (
rate(http_requests_total[5m])
)
# 错误率(用于 SLO 计算)
- record : job:http_errors:ratio5m
expr : |
sum by (job) (rate(http_requests_total{status=~"5.."}[5m]))
/
sum by (job) (rate(http_requests_total[5m]))
3.5 进阶:子查询与
label_replace
子查询(Subquery)对历史区间重算函数:
# 过去 1 小时内每分钟的 p99(用于趋势图)
histogram_quantile(0.99,
sum by (le) (
rate(http_request_duration_seconds_bucket[5m:1m])
)
)
label_replace 修改标签:
# 从 instance="10.0.1.5:8080" 提取 IP 部分
label_replace(
up,
"ip",
"$1",
"instance",
"([^:]+):.*"
)
3.6 告警规则示例
groups :
- name : slo_alerts
rules :
- alert : HighErrorRate
expr : |
job:http_errors:ratio5m > 0.01
for : 5m
labels :
severity : critical
team : backend
annotations :
summary : "服务 {{ $labels.job }} 错误率 {{ $value | humanizePercentage }}"
runbook : "https://wiki.example.com/runbooks/high-error-rate"
- alert : HighP99Latency
expr : |
job:http_request_duration_p99:rate5m > 0.5
for : 10m
labels :
severity : warning
annotations :
summary : "服务 {{ $labels.job }} P99 延迟超过 500ms"
四、Thanos:Prometheus
的全球视图
4.1 设计目标
Thanos 由 Bartłomiej Płotka(Improbable,后来 Red
Hat)等人于 2017 年创建,目标:
无限时间范围存储(对象存储)。
跨集群全局查询(多个 Prometheus 实例视为一体)。
高可用(多副本去重)。
4.2 核心组件
┌──────────────────────────────────────────────────────────────┐
│ Thanos 组件图 │
│ │
│ Prometheus──Sidecar──┐ │
│ Prometheus──Sidecar──┼──► Store Gateway ◄──► Object Store │
│ Prometheus──Sidecar──┘ │ │
│ │ │
│ Thanos Ruler ──────────────────┤ │
│ │ │
│ Thanos Receive ────────────────┤ │
│ (push 路径,支持 remote_write) │ │
│ ▼ │
│ Thanos Query ──── 全局 PromQL │
│ │ │
│ Query Frontend │
│ (缓存 + 分片查询) │
│ │ │
│ Grafana / API │
└──────────────────────────────────────────────────────────────┘
Sidecar(边车) :与 Prometheus 同 Pod
运行,功能: - 将完成写入的 2h
块上传至对象存储(S3/GCS/阿里云 OSS)。 - 暴露 Store API,供
Thanos Query 访问当前未上传的新鲜数据。
Store
Gateway(存储网关) :从对象存储按需加载块索引,响应
Thanos Query 的查询请求。支持块缓存(In-memory /
Redis)。
Compactor(合并器) :对对象存储中的块执行合并与下采样(5m/1h
分辨率),节省长期存储。全局唯一,同时只能有一个实例运行 。
Ruler(规则引擎) :在全局视图上执行告警规则和记录规则,结果写回对象存储或
Alertmanager。
Thanos Receive :接受 Remote Write,充当
Prometheus 的替代采集入口(不需要 Sidecar)。
4.3 Sidecar 配置
# thanos-sidecar Deployment
args :
- sidecar
- --prometheus.url=http://localhost:9090
- --tsdb.path=/data/prometheus
- --objstore.config-file=/etc/thanos/objstore.yaml
- --shipper.upload-compacted
- --min-time=-3h # 不缓存超过 3h 的块(由 Store 负责)
对象存储配置(阿里云 OSS):
type : OSS
config :
endpoint : "oss-cn-hangzhou.aliyuncs.com"
bucket : "company-thanos-metrics"
access_key_id : "${OSS_ACCESS_KEY}"
access_key_secret : "${OSS_SECRET}"
4.4 Query Frontend 缓存
# query-frontend 配置 Redis 缓存
query_range :
results_cache :
cache :
redis :
addr : "redis:6379"
split_queries_by_interval : 24h # 将大查询切分为 24h 分片并行执行
max_retries : 5
align_queries_with_step : true
4.5 Thanos 高可用拓扑
参见本文顶部 SVG 图(左侧)。关键点:
Prometheus 双副本 :每个集群部署两个
Prometheus,配置完全相同,抓取同一批目标。Thanos Query 通过
--store 指向两个
Sidecar,自动在返回结果时去重(基于时间戳,不基于值)。
对象存储单一来源 :两个 Sidecar
上传相同的块后,Compactor
合并时按副本标签(replica label)去重。
五、Mimir:云原生多租户
Prometheus
5.1 Cortex → Mimir
Mimir 是 Grafana Labs 于 2022 年 3 月从 Cortex fork
并彻底重构的项目,宣称相比 Cortex “40×
内存,更简单的部署”。Cortex 是最早的多租户 Prometheus
扩展方案,也是 Thanos 的竞品,由 Weaveworks 发起。
5.2 架构
写路径:
Prometheus/Agent ──remote_write──► Distributor ──► Ingester (WAL) ──► Store Gateway
│ ↑ flush
└──────────────────────────► Object Store
查询路径:
Grafana ──► Query Frontend ──► Query Scheduler ──► Querier ──► Store Gateway
│ │
缓存(Memcached/Redis) Object Store
核心微服务:
组件
职责
Distributor(分发器)
接收 Remote Write,哈希路由至 Ingester,写三副本
Ingester(摄取器)
内存 WAL + 持久化,持有最近 ~2h 数据
Store Gateway
从对象存储读取历史块,带 chunk 缓存
Querier
合并 Ingester 和 Store Gateway 的结果
Query Frontend
查询缓存、分片、重试
Compactor
后台合并 + 下采样
Alertmanager(内置)
多租户告警路由
5.3 多租户隔离
# mimir.yaml 多租户配置
multitenancy_enabled : true
# 每个租户限制
limits :
# 租户 acme 的限制
acme :
ingestion_rate : 150000 # 每秒最大样本数
ingestion_burst_size : 300000
max_global_series_per_user : 5000000
max_fetched_chunks_per_query : 2000000
ruler_max_rules_per_rule_group : 200
HTTP Header 多租户路由:
# 发送指标时带上租户 ID
curl -H "X-Scope-OrgID: acme" \
-X POST http://mimir:3100/api/v1/push \
--data-binary @payload.snappy
5.4 Helm 部署(单体模式)
# values.yaml — mimir-distributed chart
mimir :
structuredConfig :
common :
storage :
backend : s3
s3 :
bucket_name : mimir-metrics
endpoint : s3.cn-northwest-1.amazonaws.com.cn
access_key_id : ${AWS_ACCESS_KEY_ID}
secret_access_key : ${AWS_SECRET_ACCESS_KEY}
ingester :
ring :
replication_factor : 3
compactor :
data_dir : /data/compactor
store_gateway :
sharding_ring :
replication_factor : 3
六、VictoriaMetrics:高性能替代方案
6.1 设计理念
VictoriaMetrics 由 Aliaksandr Valialkin 等人于 2018
年创建,核心卖点:
存储效率 :比 Prometheus TSDB 节省 7×
磁盘空间。
写入性能 :单机 100 万 samples/s
写入不成问题。
兼容性 :完整支持 Prometheus Remote
Write 协议和 MetricsQL(PromQL 超集)。
运维简单 :单体模式只有一个二进制文件。
6.2 单体模式
# 启动单机 VictoriaMetrics
./victoria-metrics-prod \
-storageDataPath = /var/lib/victoria-metrics \
-retentionPeriod = 12 \ # 12 个月
-httpListenAddr=:8428 \
-maxConcurrentInserts = 16 \
-insert.maxQueueDuration = 1m
6.3 集群模式
集群由三个组件组成:
vminsert (写入层, 无状态)
↓ consistent hash
vmstorage (存储层, 有状态, 分片)
↑
vmselect (查询层, 无状态)
集群 Helm values:
# victoria-metrics-cluster values.yaml
vminsert :
replicaCount : 3
resources :
requests :
cpu : "2"
memory : "2Gi"
extraArgs :
maxLabelsPerTimeseries : "50"
replicationFactor : "2"
vmstorage :
replicaCount : 6
persistentVolume :
storageClass : "ssd"
size : 1Ti
resources :
requests :
cpu : "4"
memory : "16Gi"
vmselect :
replicaCount : 3
resources :
requests :
cpu : "2"
memory : "4Gi"
extraArgs :
dedup.minScrapeInterval : "15s" # 去重(当 replicationFactor > 1 时)
6.4 VMAgent
VMAgent 是 VictoriaMetrics 的专用采集器,比 Prometheus
采集效率高 2-4×:
# vmagent ConfigMap
scrape_configs :
- job_name : "kubernetes-pods"
kubernetes_sd_configs :
- role : pod
relabel_configs :
- source_labels : [ __meta_kubernetes_pod_annotation_prometheus_io_scrape ]
action : keep
regex : "true"
# 推送到集群 vminsert
remote_write :
- url : "http://vminsert:8480/insert/0/prometheus"
queue_config :
max_samples_per_send : 10000
capacity : 100000
6.5 VMAlert(告警)
# vmalert 规则
groups :
- name : vm_alerts
rules :
- alert : VMStorageDiskUsageHigh
expr : |
vm_data_size_bytes{job="vmstorage"} /
vm_free_disk_space_bytes{job="vmstorage"} > 0.8
for : 10m
labels :
severity : warning
annotations :
summary : "vmstorage 磁盘使用率超过 80%"
6.6 MetricsQL 特色函数
# 插值(VictoriaMetrics 独有,填补空洞)
interpolate(
rate(http_requests_total[5m])
)
# 滚动聚合(Rollup)
rollup(http_requests_total, "1h")
# 异常检测(实验性)
outliers_mad(
sum by (pod) (rate(container_cpu_usage_seconds_total[5m])),
4.0 # MAD 倍数
)
七、M3DB 简介
7.1 背景
M3 是 Uber 开源的分布式时序数据库,2018 年捐赠给 CNCF。在
Uber 峰值处理超过 500 亿活跃时间序列。由三个子项目组成:
M3DB :存储层,支持多副本、分片、时间范围查询。
M3Coordinator :Prometheus Remote Write
接收器,将数据路由至 M3DB。
M3Query :PromQL 查询引擎。
M3Aggregator :可选聚合层,实现实时下采样。
7.2 M3DB 架构特点
# m3dbnode 配置示意
db :
hostID :
resolver : "hostname"
namespace :
- name : metrics_0s_10s # 原始分辨率,保留 10 秒粒度,保留 2 天
resolution : 0
retention : 48h
- name : metrics_10s_2d # 10 秒分辨率,保留 2 天
resolution : 10s
retention : 48h
- name : metrics_1m_30d # 1 分钟分辨率,保留 30 天
resolution : 1m
retention : 720h
- name : metrics_10m_1y # 10 分钟分辨率,保留 1 年
resolution : 10m
retention : 8760h
replication :
factor : 3
M3DB 使用自研的 TSDB 引擎(m3tsz),支持 Gorilla
压缩(详见第七篇)。集群拓扑基于一致性哈希,支持在线扩容。
八、五者对比矩阵
8.1 技术特性对比
维度
Prometheus
Thanos
Mimir
VictoriaMetrics
M3DB
部署复杂度
★(单进程)
★★★★(6+ 组件)
★★★★★(10+ 组件)
★(单进程)/ ★★★(集群)
★★★★★
水平扩展
✗
Sidecar + 对象存储
✓(原生集群)
✓(集群模式)
✓(分片)
多租户
✗
✗(无 HTTP 隔离)
✓(原生)
✓(前缀隔离)
✓
长期存储
✗(本地)
✓(对象存储)
✓(对象存储)
✓(本地/远端)
✓(本地分片)
写入延迟
最低
低
中
最低
中
查询延迟
最低(本地)
中(跨网络)
中
低
中
磁盘占用
1×
1× + 对象存储
1× + 对象存储
0.1-0.2×
0.3-0.5×
PromQL 兼容
原生
原生
原生
MetricsQL(超集)
M3Query(近似)
社区活跃度
CNCF 毕业
CNCF 孵化
Grafana Labs
独立
CNCF 孵化
国内应用
极广
广
增长中
快速增长
较少
8.2 成本与规模适配
序列数量(活跃) 推荐方案
───────────────────────────────────────────────────────────
< 100 万 Prometheus 单机(默认选择)
100 万 - 500 万 Prometheus + Thanos(已有 K8s 集群)
或 VictoriaMetrics 单机
500 万 - 5000 万 VictoriaMetrics 集群
或 Thanos(已有团队经验)
> 5000 万 Mimir(需要多租户)
VictoriaMetrics 集群(高写入要求)
M3DB(Uber 量级,复杂度极高)
九、国内案例:VictoriaMetrics
替换 Prometheus 的迁移故事
9.1 背景
某互联网头部公司(云原生架构,多 K8s 集群,总活跃序列约 2
亿)在使用 Thanos
期间遇到如下问题(基于公开技术博客整理):
Compactor 单点瓶颈 :全局唯一 Compactor
在处理大量历史块时频繁 OOM,需人工重启。
Store Gateway
内存 :索引缓存配置不当导致每个 Store Gateway
实例占用 50 GiB 内存。
查询延迟抖动 :跨三个数据中心的 Query
延迟 P99 超过 8 秒,影响告警响应速度。
9.2 迁移方案
阶段 0(并行写入):
Prometheus ──remote_write──► Thanos Receive(现有)
└──remote_write──► VictoriaMetrics 集群(新建,接受流量 10%)
阶段 1(灰度验证,2 周):
逐步将 remote_write 流量提升到 100%,用 vmselect 验证查询结果一致性
对比查询:
curl "http://vm:8481/select/0/prometheus/api/v1/query" \
--data 'query=job:http_requests:rate5m'
curl "http://thanos-query:9090/api/v1/query" \
--data 'query=job:http_requests:rate5m'
阶段 2(切流):
Grafana 数据源指向 vmselect
保留 Thanos 只读查询 30 天(历史数据迁移)
阶段 3(历史迁移):
使用 vmctl 工具从 Prometheus/Thanos 批量导入历史块:
vmctl prometheus --prom-snapshot /data/prometheus/snapshots/xxx \
--vm-addr http://vminsert:8480 \
--vm-concurrency 8 \
--concurrency 8
9.3 迁移效果
迁移后与 Thanos
期间相比(数据来自公开博客,非实测):
指标
迁移前(Thanos)
迁移后(VictoriaMetrics)
查询 P99
8s
1.2s
磁盘占用
42 TiB
8 TiB
运维组件数
7 个
3 个
月均告警人工干预
12 次
1 次
十、工程坑点
10.1 Remote Write
背压导致数据丢失
现象 :监控图出现断点,prometheus_remote_storage_samples_failed_total
持续增加。
根因 :远端接收器(VictoriaMetrics/Thanos
Receive)写入慢,Prometheus Remote Write
队列满后主动丢弃新样本(dropped 模式)。
解决方案 :
remote_write :
- url : "http://vminsert:8480/insert/0/prometheus"
queue_config :
capacity : 50000 # 增大队列容量
max_shards : 100 # 增大并发分片
max_samples_per_send : 10000
batch_send_deadline : 10s
max_backoff : 30s # 放宽退避上限
# 启用 WAL 重放(Prometheus 2.42+ 默认开启)
同时扩容接收端:vminsert 副本从 2 增至
6,vmstorage 磁盘 IOPS 升级。
10.2
label_replace 误用导致高基数爆炸
现象 :某次上线后 Prometheus 内存从 8 GiB
暴涨至 32 GiB,active series 增加 1000 万。
根因 :有人在
relabel_configs 中使用如下规则:
# 错误示例:把 URL path 完整写入标签
relabel_configs :
- source_labels : [ __param_target ]
target_label : url
/param_target 包含完整 URL(含随机 query
string),导致每个唯一 URL 都成为新序列。
解决方案 :
# 正确:只保留 path,截断 query string
relabel_configs :
- source_labels : [ __param_target ]
regex : "https?://[^/]+(/.*) \\ ?.*"
replacement : "$1"
target_label : url_path
永远不要把高基数字段(用户 ID、trace ID、完整
URL)直接写入 Prometheus 标签。
10.3 Scrape Timeout
链式失败
现象 :某个服务 500 台 Pod
的指标全部消失,但 Pod 本身正常运行。
根因 :scrape_timeout 默认 10s,该服务
/metrics 端点需要遍历 Redis
统计数据,在业务高峰期响应时间超过 10s,触发 Prometheus 报错
context deadline exceeded,同时
up{job="xxx"} == 0
触发告警。但告警误导排查方向,以为是服务本身挂掉。
解决方案 :
scrape_configs :
- job_name : "slow-service"
scrape_timeout : 30s # 针对慢 /metrics 单独调高
scrape_interval : 60s # 同时降低抓取频率
metrics_path : /metrics/fast # 提供精简版 metrics 端点(去掉慢查询)
根本方案:优化 /metrics
端点,将耗时统计改为后台异步计算,暴露缓存值。
10.4 Thanos Compactor
单点 OOM
现象 :Compactor
进程在合并大时间范围块时因内存不足被 OOM Killer
终止,导致历史块碎片化,查询变慢。
解决方案 :
# 增大 Compactor 内存限制
# 同时开启分片(Thanos 0.29+)
thanos compact \
--objstore.config-file = /etc/thanos/objstore.yaml \
--data-dir = /data/compactor \
--consistency-delay = 30m \
--compact.blocks-fetch-concurrency = 1 \ # 限制并发取块
--wait \
--wait-interval = 5m
或切换到 VictoriaMetrics,其 compaction 在各 vmstorage
节点本地进行,无单点。
十一、选型建议与落地清单
11.1 选型决策树
Q1:你的活跃序列数量级?
< 100 万 → Prometheus 单机 + 本地磁盘(2 周)→ 结束
100 万 - 500 万 → Q2
> 500 万 → Q3
Q2:是否已有 Thanos 经验或团队熟悉 Go 生态?
是 → Prometheus + Thanos(对象存储打通)
否 → VictoriaMetrics 单机(最省运维)
Q3:是否有多租户需求(多业务线共享一套 Prometheus)?
是 → Mimir(原生多租户)或 VictoriaMetrics Cluster(前缀隔离)
否 → VictoriaMetrics Cluster
超大规模(> 10 亿序列 / Uber 量级)→ M3DB(慎重评估运维成本)
11.2 工程落地清单
确认
scrape_interval 与业务 SLO 匹配(一般
15s,告警关键指标 5s)
所有 Recording Rules
在仪表盘查询中使用(禁止仪表盘直接跑昂贵
PromQL)
部署
prometheus_active_native_histograms
监控基数趋势
Remote Write
队列监控(prometheus_remote_storage_pending_samples)设告警
配置
--storage.tsdb.retention.time 和
--storage.tsdb.retention.size
双重保护
Prometheus
PodDisruptionBudget + 副本数 ≥ 2(双副本去重)
标签命名规范:遵循
Prometheus 官方 Best
Practices(小写、下划线分隔、无空格)
新上线服务必须经过基数审查(利用
prometheus-cardinality-inspector
工具)
对象存储桶设置生命周期规则(原始数据 >
2y 迁移至冷存储)
参考资料
Prometheus 官方文档 — https://prometheus.io/docs/
Thanos 官方文档 — https://thanos.io/tip/thanos/
VictoriaMetrics 文档 — https://docs.victoriametrics.com/
Grafana Mimir 文档 — https://grafana.com/docs/mimir/
M3DB 文档 — https://m3db.io/docs/
Björn Rabenstein, “Prometheus Storage” (PromCon
2017)
Bartłomiej Płotka, “Thanos: Prometheus at Scale”
(KubeCon EU 2019)
阿里云 PolarDB 团队, “从 Thanos 迁移到 VictoriaMetrics
的实践” (InfoQ 2023) — https://www.infoq.cn/
Aliaksandr Valialkin, “How VictoriaMetrics makes writes
faster” (VictoriaMetrics blog, 2022)
Uber Engineering, “M3: Uber’s Open Source, Large-scale
Metrics Platform for Prometheus” (2018) — https://www.uber.com/blog/
Grafana Labs, “Cortex and Thanos: A technical
comparison” (Grafana blog)
Rob Skillington, “Introducing M3” (KubeCon NA 2018)
上一篇 :数据模型:时间序列、日志、Span、Profile
的内部表达
下一篇 :时序数据库内核:TSM、TSI、倒排索引与
Gorilla 压缩
同主题继续阅读 把当前热点继续串成多页阅读,而不是停在单篇消费。
2026-04-22 · architecture / observability
深入时序数据库的存储内核:Prometheus TSDB 的 WAL 与块管理、InfluxDB 的 TSM 引擎与 TSI 倒排索引、Gorilla 压缩算法的数学原理、VictoriaMetrics mergeset 架构、ClickHouse MergeTree 作为 metrics 后端,以及国内大厂在 series churn 和 compaction 风暴上踩过的坑。
2026-04-22 · architecture / observability
从控制论到云原生:拆解可观测性的五大信号支柱,对比监控与可观测性的本质区别,梳理开源/商业/SaaS 分类,以及国内互联网公司三大支柱落地现状与典型工程坑点。
2026-04-22 · architecture / observability
从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。
2026-04-22 · architecture / observability
监控与可观测性不是新旧迭代,而是认知模型的根本转换。本文梳理从 1999 年 Nagios 到 2019 年 OpenTelemetry 的二十年演进时间线,对比 push/pull 模型、数据模型差异,以及国内从 Zabbix 到 Prometheus 再到 OTel 的典型迁移路径与工程坑点。