---
title: 指标与告警
url: https://doc.liz6.com/distributed-systems/08-observability/02-metrics-and-alerts
locale: zh
area: distributed-systems
tags:
- distributed-systems
- 可观测性
date: 2026-06-30
modified: 2026-07-11
description: RED(Rate/Errors/Duration)看服务端的外部视角,USE(Utilization/Saturation/Errors)看资源的内部视角——两者互补。SLI 是实际测量值,SLO 是承诺目标,SLA 是违约后果。告警设计的第一原则:page 只对人需要立即行动的事,其他进 dashboard——误报…
---

# 指标与告警

> RED(Rate/Errors/Duration)看服务端的外部视角,USE(Utilization/Saturation/Errors)看资源的内部视角——两者互补。SLI 是实际测量值,SLO 是承诺目标,SLA 是违约后果。告警设计的第一原则:page 只对人需要立即行动的事,其他进 dashboard——误报会训练值班工程师忽略告警,比漏报告更危险。

## RED 与 USE 方法论

两个互补的视角：

### RED (Rate, Errors, Duration)

面向**服务**——每个 service endpoint:

- **Rate**: 每秒请求数——了解流量模式
- **Errors**: 失败率——500s, 超时, 连接错误
- **Duration**: 延迟分布（P50/P90/P99/P99.9）——用户体验

RED 适合所有在线服务（HTTP/gRPC worker），每个 endpoint 至少 3 个 metrics。

### USE (Utilization, Saturation, Errors)

面向**资源**——CPU, memory, disk, network:

- **Utilization**: 资源的使用率（CPU%, memory bytes）
- **Saturation**: 资源的等待队列（CPU run queue, memory OOM score, IO await）
- **Errors**: 资源的错误（disk IO errors, NIC errors, dropped packets）

USE 适合所有物理/虚拟资源——在它们达到 usage limit 之前提前检测。

## Prometheus HA

Prometheus 本身无状态——scrape on each instance。高可用靠两个相同实例独立 scrape:

<svg viewBox="0 0 720 320" xmlns="http://www.w3.org/2000/svg" font-family="-apple-system,'Source Han Sans CN','Microsoft YaHei',sans-serif" role="img" aria-label="Prometheus HA 架构:两实例独立 scrape 相同 targets,remote_write 汇入 Thanos 去重">
  <defs>
    <marker id="pha" markerWidth="10" markerHeight="8" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#475569"/></marker>
  </defs>
  <rect width="720" height="320" fill="#ffffff"/>
  <text x="360" y="28" text-anchor="middle" font-size="17" font-weight="700" fill="#1f2933">Prometheus HA:两实例独立 scrape,remote_write 汇入长期存储去重</text>

  <rect x="40" y="56" width="150" height="44" rx="8" fill="#4f46e5"/>
  <text x="115" y="83" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Prometheus A</text>

  <rect x="530" y="56" width="150" height="44" rx="8" fill="#4f46e5"/>
  <text x="605" y="83" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Prometheus B</text>

  <rect x="290" y="45" width="140" height="50" rx="8" fill="#e2e8f0" stroke="#cbd5e1"/>
  <text x="360" y="66" text-anchor="middle" font-size="12.5" font-weight="700" fill="#334155">targets</text>
  <text x="360" y="82" text-anchor="middle" font-size="9.5" fill="#64748b">A、B 各自独立抓取,目标相同</text>

  <line x1="190" y1="78" x2="288" y2="68" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="235" y="64" text-anchor="middle" font-size="10" fill="#475569">scrape</text>

  <line x1="530" y1="78" x2="432" y2="68" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="485" y="64" text-anchor="middle" font-size="10" fill="#475569">scrape</text>

  <rect x="250" y="190" width="220" height="56" rx="10" fill="#0d9488"/>
  <text x="360" y="213" text-anchor="middle" font-size="13" font-weight="700" fill="#ffffff">Thanos / Cortex / Mimir</text>
  <text x="360" y="232" text-anchor="middle" font-size="11" fill="#ccfbf1">聚合 · 去重 · 长期存储</text>

  <line x1="115" y1="100" x2="300" y2="190" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="180" y="127" text-anchor="middle" font-size="10" fill="#475569">remote_write</text>

  <line x1="605" y1="100" x2="420" y2="190" stroke="#475569" stroke-width="1.6" marker-end="url(#pha)"/>
  <text x="540" y="127" text-anchor="middle" font-size="10" fill="#475569">remote_write</text>

  <rect x="60" y="266" width="600" height="42" rx="8" fill="#f0fdfa" stroke="#99f6e4"/>
  <text x="76" y="284" font-size="12.5" fill="#115e59">相同 targets 各自独立抓取,双份数据经 remote_write 汇入 Thanos;Grafana 查询时按</text>
  <text x="76" y="301" font-size="12.5" fill="#115e59">external_labels 区分两副本,自动去重同一份 time series。</text>
</svg>

Grafana 查询 Thanos → 自动去重 A 和 B 的 same time series（利用 Prometheus 的 `external_labels` 区分）。

## SLI → SLO → SLA

```
SLI (Service Level Indicator): 实际测量的指标
  例: 过去 28 天的 GET /api success rate = 99.95%

SLO (Service Level Objective): 我们承诺的目标
  例: GET /api success rate >= 99.9%
  
SLA (Service Level Agreement): 不达目标的后果
  例: 若 SLO 不达 → 赔 10% credit

Error budget = 100% - SLO = 0.1%
  可以"烧"掉: 如果实在要发快速 hotfix (可能短暂破坏 SLO), error budget 是你的"配额"
```

## Alert 设计原则

1. **Page only on user-visible SLO violation**: 如果指标显示 `P99 latency > 500ms` 但用户仍能使用，不应 pager。只有 `4xx/5xx rate > SLO` 时发 page
2. **Symptom over cause**: alert 应该是"用户看到 500 errors"，不是"CPU 70% 了"
3. **Eliminate noise**: 每个告警都要有明确的 actionable runbook，否则 → 降级为 ticket
4. **Tune for sensitivity vs specificity**: `for: 5m` (至少持续 5 分钟才 fire) 过滤短暂毛刺。`for` 越长 → 检的越晚，但 false positive 越少

## 误报治理

```
常见误报原因:
  - 阈值固定 (P99=200ms)，但白天 vs 夜间流量模式不同 → 用 percentile over larger window
  - Alert 在部署期间触发 → 加 maintenance window or suppress during rollout
  - 误报过多 → alert 被忽略 → 真正的故障漏掉 → 这叫 alarm fatigue
```

治理：定期 review alert fires——哪些 alert 触发了但没有对应的用户影响？→ 调高阈值 or 改为 ticket。

## 参考

- **Google SRE Book**: Chapter 6 — Monitoring Distributed Systems
- **USE Method**: brendangregg.com/usemethod.html
- **RED Method**: grafana.com/blog/2018/08/02/the-red-method-how-to-instrument-your-services

*Keywords: RED, USE, SLI, SLO, SLA, error budget, Prometheus HA, alert design, alarm fatigue*
