2. 误差预算台账设计

误差预算台账是告警降噪与阈值联动的“会计账簿”。没有台账,SRE 团队就无法回答“我们还有多少故障余量”“当前消耗速度是否危险”等核心问题。本章从数据结构与存储选型两个维度,构建可落地的误差预算台账体系。

2.1 台账数据结构设计

误差预算台账的核心是时间窗口、预算总量、已消耗量、剩余量四要素。设计时需区分滚动窗口与固定窗口两种模式,并定义消耗计算规则。

2.1.1 时间窗口模型

窗口类型 定义 适用场景 示例
滚动窗口 以当前时刻为终点,向前滑动固定时长 实时监控、动态告警 过去 28 天的滑动窗口
固定窗口 按自然日历周期(周/月/季度)划分 财务核算、SLO 报告 2025 年 3 月自然月
混合窗口 滚动窗口 + 固定窗口联合计算 既有实时告警又有月度报告 滚动 28 天 + 当月累计
实践建议:生产环境优先使用滚动窗口作为告警依据,固定窗口用于管理层汇报。两者可并存,但告警阈值必须基于滚动窗口,避免月末“突击消耗”导致漏报。

2.1.2 台账字段定义

每条误差预算记录应包含以下核心字段:

{
  "service_name":    "payment-api",          // 服务标识
  "slo_name":        "latency_p99_500ms",    // SLO 名称
  "window_type":     "rolling",              // 窗口类型
  "window_seconds":  2419200,                // 28 天 = 2419200 秒
  "budget_total":    0.999,                  // 预算总量(99.9%)
  "good_events":     8640000,                // 好事件数
  "total_events":    8648640,                // 总事件数
  "budget_consumed": 0.001,                  // 已消耗量
  "budget_remaining": 0.998,                 // 剩余量
  "consumption_rate": 0.0000357,             // 消耗速率(/小时)
  "burn_rate":       0.5,                    // 燃烧速率
  "recorded_at":     "2025-03-15T10:00:00Z"  // 记录时间戳
}

2.1.3 消耗计算规则

  1. 预算总量 = 1 - SLO 目标值(例如 SLO 99.9% → 预算总量 0.001)
  2. 已消耗量 = 1 - (好事件数 / 总事件数)
  3. 剩余量 = 预算总量 - 已消耗量
  4. 燃烧速率 = 已消耗量 / (窗口时长 × 预算总量)
关键公式:当剩余量 ≤ 0 时,SLO 已被违反;当燃烧速率 > 1 时,表示消耗速度超过预算分配速度,需要触发告警。

2.2 台账存储选型

误差预算台账需要同时支持高写入吞吐(每秒数千条记录)、低延迟查询(告警判定 < 1s)、历史回溯(90 天以上)。三种主流方案对比如下:

维度 Prometheus Thanos ClickHouse
存储模型 时序数据库(TSDB) Prometheus + 对象存储 列式存储
写入性能 单机 100 万样本/秒 水平扩展,无上限 单机 50 万行/秒
查询延迟 毫秒级(近期数据) 毫秒级(近期),秒级(历史) 毫秒级(全量数据)
历史数据保留 本地有限(通常 15-30 天) 无限(对象存储) 无限(按分区管理)
告警集成 原生 Alertmanager 兼容 Alertmanager 需额外开发
运维复杂度 低 中 高
成本 中(SSD 存储) 低(对象存储) 中(按需计算资源)
选型避坑:不要只用 Prometheus 存储误差预算台账。Prometheus 的本地存储无法长期保留历史预算数据,且单机容量有限。生产环境至少使用 Thanos 或 ClickHouse 作为长期存储。

2.3 推荐架构:Thanos + ClickHouse 分层存储

结合两种存储的优势,推荐采用分层台账架构:

误差预算台账分层存储架构 数据采集层 Prometheus Exporter / OpenTelemetry Collector / 自定义指标采集器 实时计算层 Prometheus Rule / Recording Rule 实时计算预算消耗与燃烧速率 热存储(近期 7 天) Thanos Receive / Prometheus 毫秒级查询,支持实时告警 冷存储(历史 90 天+) ClickHouse / Thanos Store 列式压缩,低成本长期保留 查询与告警层 Grafana 仪表盘 / Alertmanager 告警 / 自定义 API 查询

2.4 台账表结构设计(ClickHouse 示例)

若选择 ClickHouse 作为历史存储,推荐使用物化视图 + 聚合表结构:

-- 原始事件表(按天分区)
CREATE TABLE error_budget_events (
  service_name    String,
  slo_name        String,
  window_type     String,
  window_seconds  UInt32,
  good_events     UInt64,
  total_events    UInt64,
  recorded_at     DateTime
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(recorded_at)
ORDER BY (service_name, slo_name, recorded_at);

-- 聚合台账表(每小时聚合)
CREATE MATERIALIZED VIEW error_budget_hourly
ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(hour)
ORDER BY (service_name, slo_name, hour)
AS SELECT
  service_name,
  slo_name,
  toStartOfHour(recorded_at) AS hour,
  sum(good_events) AS total_good,
  sum(total_events) AS total_events
FROM error_budget_events
GROUP BY service_name, slo_name, hour;
查询优化:使用 SummingMergeTree 引擎自动合并相同主键的行,查询时直接读取聚合结果,避免全表扫描。对于 90 天数据,单次预算查询可在 50ms 内完成。

2.5 台账数据生命周期管理

数据层级 保留时长 存储介质 查询用途
热数据 最近 7 天 Prometheus / Thanos Receive 实时告警、燃烧速率计算
温数据 7 ~ 30 天 Thanos Store (对象存储) 周报、趋势分析
冷数据 30 ~ 90 天 ClickHouse 月度 SLO 报告、审计
归档数据 90 天以上 对象存储(压缩后) 合规审计、年度复盘
台账设计核心原则:写入路径要简单(避免复杂 JOIN),查询路径要快速(预聚合 + 索引),存储成本要可控(分层 + 压缩)。误差预算台账不是 OLTP 系统,不要追求事务一致性,接受最终一致性。