惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
P
Privacy International News Feed
Security Latest
Security Latest
H
Hacker News: Front Page
T
Tenable Blog
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Security @ Cisco Blogs
Project Zero
Project Zero
O
OpenAI News
AI
AI
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
NISL@THU
NISL@THU
A
Arctic Wolf
T
Threat Research - Cisco Blogs
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
U
Unit 42
S
Security Affairs
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
月光博客
月光博客
Engineering at Meta
Engineering at Meta
腾讯CDC
F
Full Disclosure
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
The Cloudflare Blog

土法炼钢兴趣小组的算法知识备份

国密算法与国密 TLS 系列索引 【系统架构设计】架构质量属性:不只是"高可用高性能" 【系统架构设计百科】告警策略:如何避免"狼来了" 【系统架构设计】CQRS:读写分离的架构哲学 【系统架构设计】空间架构:极端扩展场景的解法 【系统架构设计】微服务架构深度审视:优势、代价与适用边界 【系统架构设计】扩展性原理:水平、垂直与对角扩展 【系统架构设计】无状态设计:扩展的第一步也是最难的一步 【系统架构设计】缓存架构:从本地到分布式的多级缓存体系 【系统架构设计】管道与过滤器:Unix 哲学的架构表达 【系统架构设计】复杂性管理:架构的核心战场 【系统架构设计】消息队列架构:异步解耦的设计与陷阱 【系统架构设计】CDN 架构:全球加速的设计原理 【系统架构设计】连接池设计:被忽视的性能杀手 【系统架构设计】弹性设计模式:熔断器、舱壁与超时 【系统架构设计】高可用设计模式:冗余、故障转移与仲裁 【系统架构设计】容量规划:从拍脑袋到数据驱动 【系统架构设计】数据库扩展:分库分表的工程实践与替代方案 【系统架构设计】SLO 工程:可靠性的量化管理 【系统架构设计】性能建模:用数学思维分析系统瓶颈 【系统架构设计】混沌工程:主动验证系统的韧性 【系统架构设计】零拷贝与内存映射:数据搬运的极致优化 【系统架构设计】线程模型:从 thread-per-request 到协程 【系统架构设计】容灾架构:多活与灾备设计 【系统架构设计】数据库性能模式:索引、查询与连接管理 【系统架构设计】数据建模:从关系范式到文档模型的真实权衡 【系统架构设计】吞吐量优化:批处理、流水线与并发模型 【系统架构设计】流处理架构:从批处理到实时的范式迁移 【系统架构设计】搜索引擎架构:倒排索引之上的系统设计 【系统架构设计】时序数据架构:监控与 IoT 的存储设计 【系统架构设计】数据迁移与版本化:在线不停机的数据演进 【系统架构设计】数据湖与数据仓库:分析架构的演进路线 【系统架构设计】API 网关设计:入口层的职责边界 【系统架构设计】应用层数据一致性模式:在正确性与性能之间走钢丝 【系统架构设计】多模数据库选型:Polyglot Persistence 的工程实践 【系统架构设计】服务发现与注册:动态拓扑的基础设施 【系统架构设计】配置管理架构:从配置文件到配置中心 【系统架构设计】全链路压测:大规模系统的性能验证 【系统架构设计】幂等性设计:分布式环境下的安全重试 【系统架构设计】契约测试与 Schema 演进:服务间的信任协议 【系统架构设计】长连接与推送架构:WebSocket、SSE 与 MQTT 【系统架构设计】延迟分析:从 P50 到 P999 的全链路追踪 【系统架构设计百科】DDD 战术模式:聚合、实体与值对象 【系统架构设计百科】防腐层与开放主机服务:系统集成的 DDD 方案 【系统架构设计百科】领域事件与事件风暴:从业务到架构的桥梁 【系统架构设计百科】CQRS + Event Sourcing 完整实战:从领域建模到部署 【系统架构设计百科】DDD 与微服务:用领域模型划分服务边界 【系统架构设计】DDD 战略设计:限界上下文与上下文映射 【系统架构设计百科】认证架构:从 Session 到 JWT 到 OIDC 【系统架构设计】API 设计哲学:REST vs GraphQL vs gRPC 的真实权衡 排序算法专题:从 TimSort 到并行排序 【密码学百科】国密算法体系:SM2/SM3/SM4/SM9 全景解读 【密码学百科】承诺方案:Pedersen 承诺、向量承诺与多项式承诺 【密码学百科】不经意传输与隐私信息检索:OT、OT 扩展与 PIR 【密码学百科】门限密码学:门限签名、门限解密与分布式密钥生成 完美哈希:从理论到 gperf 实践 【密码学百科】安全多方计算:从 Yao 的混淆电路到实用 MPC 【密码学百科】同态加密:从 Paillier 到全同态加密(FHE) 【密码学百科】零知识证明系统:zk-SNARKs、zk-STARKs 与 Bulletproofs 【密码学百科】概率论与密码分析:生日攻击、差分分析与线性分析 【密码学百科】计算复杂性与归约:密码安全性证明的基石 【密码学百科】秘密共享:Shamir 方案、VSS 与安全多方计算入口 【密码学百科】椭圆曲线代数:Weierstrass 方程、点群运算与曲线选择 【密码学百科】离散对数与配对密码学:从 DLP 到 BLS 签名 【密码学百科】格密码数学基础:SVP、LWE 与格基约化 【密码学百科】抽象代数:群、环、域的密码学视角 【密码学百科】有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用 【密码学百科】数论进阶:二次剩余、椭圆曲线上的 Weil 配对 【密码学百科】密码学简史:从凯撒密码到量子时代 【密码学百科】威胁模型与安全目标:CIA 三要素之外 【密码学百科】Kerckhoffs 原则与现代密码设计哲学 【密码学百科】随机性:密码学的基石 【密码学百科】信息论入门:熵、完美保密与 Shannon 定理 【密码学百科】分组密码原理:Feistel 网络与 SPN 结构 【密码学百科】AES 逐步拆解:SubBytes 到 MixColumns 的数学 【密码学百科】分组密码工作模式全览:ECB/CBC/CTR/OFB/CFB 【密码学百科】流密码:RC4 的兴衰与 ChaCha20 的崛起 【密码学百科】密码学哈希函数:MD5→SHA-2→SHA-3 的进化之路 【密码学百科】MAC 与 HMAC:消息认证的正确姿势 【密码学百科】认证加密(AEAD):GCM、ChaCha20-Poly1305 与 OCB 【密码学百科】密钥派生函数:HKDF、PBKDF2、Argon2 与密码存储 【密码学百科】公钥密码的数论基础:模运算、群、原根 【密码学百科】RSA 从原理到攻击:教科书 RSA 为什么不安全 【密码学百科】Diffie-Hellman 密钥交换与离散对数问题 【密码学百科】椭圆曲线密码学(ECC):从几何直觉到点群运算 【密码学百科】数字签名:ECDSA、EdDSA 与 Schnorr 签名 【密码学百科】现代密钥交换:X25519、ECDHE 与前向保密 【密码学百科】混合加密与 KEM/DEM 范式:ECIES 与 HPKE 【密码学百科】填充方案:PKCS#1 v1.5、OAEP 与 PSS 【密码学百科】TLS 协议全解析:从握手到 0-RTT 【密码学百科】PKI 与数字证书:信任链的构建与崩塌 【密码学百科】密码认证协议:从 SRP 到 OPAQUE 【密码学百科】零知识证明入门:如何证明你知道而不泄露 【密码学百科】安全信道构造:Noise 协议框架与 Signal 协议 【密码学百科】密钥管理工程:HSM、KMS 与密钥生命周期 【密码学百科】侧信道攻击:从时序攻击到功耗分析 【密码学百科】密码学实现陷阱:三层漏洞分类、审计工具链与系统性预防 密码敏捷性:如何设计可升级的密码系统 【密码学百科】OpenSSL/BoringSSL 架构剖析:ENGINE、Provider 与 FIPS 模块 排序基准测试:用数据说话
【可观测性工程】Metrics:Prometheus、VictoriaMetrics、Thanos、Mimir、M3
2026-04-22 · via 土法炼钢兴趣小组的算法知识备份

度量指标(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_configsconsul_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_headblock)。
  • 压缩(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 年创建,目标:

  1. 无限时间范围存储(对象存储)。
  2. 跨集群全局查询(多个 Prometheus 实例视为一体)。
  3. 高可用(多副本去重)。

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× + 对象存储 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 工程落地清单


参考资料

  1. Prometheus 官方文档 — https://prometheus.io/docs/
  2. Thanos 官方文档 — https://thanos.io/tip/thanos/
  3. VictoriaMetrics 文档 — https://docs.victoriametrics.com/
  4. Grafana Mimir 文档 — https://grafana.com/docs/mimir/
  5. M3DB 文档 — https://m3db.io/docs/
  6. Björn Rabenstein, “Prometheus Storage” (PromCon 2017)
  7. Bartłomiej Płotka, “Thanos: Prometheus at Scale” (KubeCon EU 2019)
  8. 阿里云 PolarDB 团队, “从 Thanos 迁移到 VictoriaMetrics 的实践” (InfoQ 2023) — https://www.infoq.cn/
  9. Aliaksandr Valialkin, “How VictoriaMetrics makes writes faster” (VictoriaMetrics blog, 2022)
  10. Uber Engineering, “M3: Uber’s Open Source, Large-scale Metrics Platform for Prometheus” (2018) — https://www.uber.com/blog/
  11. Grafana Labs, “Cortex and Thanos: A technical comparison” (Grafana blog)
  12. Rob Skillington, “Introducing M3” (KubeCon NA 2018)

上一篇数据模型:时间序列、日志、Span、Profile 的内部表达

下一篇时序数据库内核:TSM、TSI、倒排索引与 Gorilla 压缩

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-04-22 · architecture / observability

【可观测性工程】时序数据库内核:TSM、TSI、倒排索引与 Gorilla 压缩

深入时序数据库的存储内核:Prometheus TSDB 的 WAL 与块管理、InfluxDB 的 TSM 引擎与 TSI 倒排索引、Gorilla 压缩算法的数学原理、VictoriaMetrics mergeset 架构、ClickHouse MergeTree 作为 metrics 后端,以及国内大厂在 series churn 和 compaction 风暴上踩过的坑。

2026-04-22 · architecture / observability

可观测性工程

从 Metrics、Logs、Traces 到 Profiling、eBPF、OpenTelemetry 与 SLO 治理,面向中国工程团队的可观测性系统化手册。