MTTR 与 MTBF 体系详解
MTTR 与 MTBF 体系详解
一句话:MTTR 衡量”出了事多快能恢复”,MTBF 衡量”多久出一次事”——两者合起来描述系统的可靠性画像,是稳定性体系最核心的度量指标。
概述
SLO 回答”多稳才算稳”,MTTR/MTBF 回答”出了事怎么办、多久出一次”。它们是稳定性体系的两条腿:
- MTBF(Mean Time Between Failures):平均故障间隔时间,越长越好 → 预防能力
- MTTR(Mean Time To Recovery):平均恢复时间,越短越好 → 响应能力
关键认知:
可用性 = MTBF / (MTBF + MTTR)。提升可用性有两条路——拉长 MTBF(少出事)或缩短 MTTR(快恢复)。99.9% 可用性意味着每月允许 ~43 分钟故障,这 43 分钟就是 MTTR 的预算。
MTTR 分解:四个关键子指标
MTTR 不是单一数字,而是一条时间链:
graph LR
FAIL[故障发生] -->|MTTD| DETECT[告警触发]
DETECT -->|MTTA| ACK[人工响应]
ACK -->|MTTI| IDENTIFY[定位根因]
IDENTIFY -->|MTTR_restore| RESTORE[完全恢复]
FAIL -.->|MTTR 总时间| RESTORE
| 子指标 | 全称 | 含义 | 典型值 | 优化方向 |
|---|---|---|---|---|
| MTTD | Mean Time To Detect | 故障发生到告警触发 | 1-5 min | 监控覆盖率、异常检测、SLO 燃烧率告警 |
| MTTA | Mean Time To Acknowledge | 告警到 On-Call 开始处理 | 2-10 min | 告警路由、值班轮换、升级策略 |
| MTTI | Mean Time To Identify | 开始处理到定位根因 | 5-30 min | 排查方法论、可观测性、工具链 |
| MTTR_restore | Mean Time To Restore | 定位根因到完全恢复 | 5-60 min | 回滚、自愈、应急预案、灾备切换 |
MTTR = MTTD + MTTA + MTTI + MTTR_restore
各子指标的优化手段
MTTD 优化:
├── SLO 多窗口多燃烧率告警(MWMBR)→ 减少误报,快速捕捉真实故障
├── 黄金信号全覆盖(延迟/流量/错误/饱和度)
├── 异常检测算法(时序预测 + 动态阈值)
└── 关键路径心跳检测(主动探活)
MTTA 优化:
├── 告警分级(Page vs Ticket)→ 只 Page 真正紧急的
├── Alertmanager 分组 + 抑制 → 防告警风暴
├── On-Call 轮换 + 升级策略 → 确保有人响应
└── 移动端推送(PagerDuty / 飞书 / 企微)
MTTI 优化:
├── K8s 故障排查方法论(分层排查)
├── 分布式追踪(OpenTelemetry → Jaeger/Tempo)
├── 日志聚合 + 关联查询(Loki / ELK)
├── 指标→链路下钻(exemplar)
└── RCA 方法论(5-Whys / 故障树)
MTTR_restore 优化:
├── 一键回滚(CI/CD 流水线内置)
├── 故障自愈(自动重启 / 自动扩容 / 自动切换)
├── 应急预案 Runbook(标准化操作步骤)
└── 灾备切换(多 AZ / 多 Region failover)
MTBF 优化:减少故障发生频率
MTBF 的提升依赖预防体系建设:
| 预防手段 | 做法 | 效果 |
|---|---|---|
| 变更管控 | 灰度发布、评审机制、冻结窗口、自动回滚 | 减少 60%+ 的人为故障 |
| 容量规划 | 压测推演、资源预留、弹性伸缩、容量预警 | 避免容量超限导致的级联故障 |
| 高可用架构 | 冗余部署、多 AZ、故障转移、依赖降级 | 单点故障不影响整体可用性 |
| 混沌工程 | 主动注入故障,验证恢复能力 | 提前发现隐藏风险 |
| 代码质量 | CI 门禁、自动化测试、静态分析 | 减少代码缺陷上线 |
| 依赖治理 | 依赖版本锁定、兼容性测试、替代方案 | 避免上游变更引入故障 |
计算方法与实战
MTTR 计算
import datetime
from dataclasses import dataclass
@dataclass
class Incident:
incident_id: str
start_time: datetime.datetime # 故障发生时间
detect_time: datetime.datetime # 告警触发时间
ack_time: datetime.datetime # 人工响应时间
identify_time: datetime.datetime # 定位根因时间
resolve_time: datetime.datetime # 完全恢复时间
def calculate_mttr_metrics(incidents: list[Incident]) -> dict:
"""计算 MTTR 及其子指标"""
if not incidents:
return {}
total = len(incidents)
mttd = sum((i.detect_time - i.start_time).total_seconds() for i in incidents) / total
mtta = sum((i.ack_time - i.detect_time).total_seconds() for i in incidents) / total
mtti = sum((i.identify_time - i.ack_time).total_seconds() for i in incidents) / total
mttr_restore = sum((i.resolve_time - i.identify_time).total_seconds() for i in incidents) / total
mttr = sum((i.resolve_time - i.start_time).total_seconds() for i in incidents) / total
return {
"MTTD_sec": mttd,
"MTTA_sec": mtta,
"MTTI_sec": mtti,
"MTTR_restore_sec": mttr_restore,
"MTTR_sec": mttr,
"MTTR_min": mttr / 60,
# 找出最慢的环节
"bottleneck": max(
[("MTTD", mttd), ("MTTA", mtta), ("MTTI", mtti), ("restore", mttr_restore)],
key=lambda x: x[1]
)[0],
}
MTBF 计算
def calculate_mtbf(incidents: list[Incident],
window_start: datetime.datetime,
window_end: datetime.datetime) -> dict:
"""计算 MTBF"""
total_window = (window_end - window_start).total_seconds()
num_failures = len(incidents)
if num_failures <= 1:
return {"MTBF_sec": total_window, "note": "样本不足,仅一个故障窗口"}
# MTBF = 总运行时间 / 故障次数
# 总运行时间 = 窗口时间 - 总故障时间(MTTR 总和)
total_downtime = sum(
(i.resolve_time - i.start_time).total_seconds() for i in incidents
)
uptime = total_window - total_downtime
mtbf = uptime / num_failures
# 可用性
availability = uptime / total_window
return {
"MTBF_sec": mtbf,
"MTBF_hours": mtbf / 3600,
"total_failures": num_failures,
"total_downtime_sec": total_downtime,
"uptime_sec": uptime,
"availability": f"{availability * 100:.3f}%",
}
SLO 与 MTTR/MTBF 的关系
| SLO | 每月允许不可用 | MTBF 要求 | MTTR 要求 |
|---|---|---|---|
| 99% | 432 min | 每 3 天 1 次故障 | 每次 43 min |
| 99.9% | 43.2 min | 每月 1 次故障 | 每次 43 min |
| 99.95% | 21.6 min | 每月 1 次故障 | 每次 21 min |
| 99.99% | 4.32 min | 每季 1 次故障 | 每次 4 min |
| 99.999% | 0.43 min | 几乎不允许故障 | 每次 26 sec |
关键洞察:SLO 越高,MTTR 要求越苛刻。99.99% 意味着 MTTR 不能超过 4.3 分钟——这基本排除了人工介入,必须靠自愈 + 自动切换。
MTTR/MTBF 度量看板
Grafana Dashboard 设计
# MTTR/MTBF 看板关键 Panel
panels:
- title: "MTTR 趋势(30 天滚动)"
type: stat
query: |
# 基于 Alertmanager 告警记录
avg_over_time(
(time() - alert_start_timestamp{alertstate="resolved"})[30d:1d]
)
- title: "MTTR 分解(按子指标)"
type: bargauge
# MTTD / MTTA / MTTI / restore 各占多少
- title: "MTBF 趋势(30 天滚动)"
type: stat
query: |
# 总运行时间 / 故障次数
- title: "可用性趋势"
type: timeseries
query: |
# uptime / (uptime + downtime) * 100
- title: "故障频次(按严重程度)"
type: piechart
# SEV1 / SEV2 / SEV3 分布
- title: "Top 10 根因分类"
type: bargauge
# 按根因分类聚合 MTTR
- title: "MTTR 瓶颈环节"
type: gauge
# 哪个子指标最慢
告警规则示例
# MTTR 超过 SLO 预算告警
- alert: MTTRExceedsBudget
expr: |
avg_over_time(
incident_mttr_seconds[7d]
) > 1800 # 30 分钟
for: 10m
labels:
severity: ticket
team: sre
annotations:
summary: "MTTR 超过 30 分钟预算"
description: "过去 7 天平均 MTTR = {{ $value }} 秒,超过 SLO 预算"
# MTBF 下降告警(故障频率上升)
- alert: MTBFDecreasing
expr: |
(
count_over_time(alertmanager_notifications_total{alertstate="resolved"}[7d])
>
count_over_time(alertmanager_notifications_total{alertstate="resolved"}[7d] offset 7d)
)
for: 1h
labels:
severity: ticket
annotations:
summary: "故障频率上升,MTBF 下降"
常见问题 / 坑点
| 问题 | 原因 | 解决方案 |
|---|---|---|
| MTTR 数据不准 | 故障开始/结束时间记录不规范 | 建立标准化时间戳采集(Alertmanager webhook + 工单系统联动) |
| 只看总 MTTR 不看分解 | 不知道瓶颈在哪 | 必须分解到 MTTD/MTTA/MTTI/restore,找出最慢环节 |
| MTBF 样本太少 | 高 SLO 系统故障少 | 拉长统计窗口(季度/年度),或用混沌工程主动”制造”故障样本 |
| 可用性计算忽略部分降级 | 只算”全挂”才算故障 | 定义清晰的”故障”口径:SLI 违反即算故障,不论是否全挂 |
| MTTR 数据靠人工填 | 记录不及时、不准 | 从 Alertmanager + 工单系统自动采集,不依赖人工录入 |
实践:从零建设 MTTR/MTBF 度量
第 1 步:定义故障口径
"故障"定义:
- SEV1:核心服务 SLI 违反(成功率 < SLO / 延迟 > SLO)
- SEV2:非核心服务 SLI 违反 或 核心服务部分降级
- SEV3:单实例故障 / 非用户可感知的内部异常
第 2 步:自动采集时间戳
# Alertmanager Webhook → 时间戳采集服务
from flask import Flask, request
import datetime
app = Flask(__name__)
@app.route("/webhook", methods=["POST"])
def collect_timestamps():
data = request.json
alert = data.get("alerts", [{}])[0]
if data.get("status") == "firing":
# 故障检测时间
record_incident_start(
alert_id=alert["fingerprint"],
detect_time=datetime.datetime.now(),
alert_name=alert["labels"]["alertname"],
severity=alert["labels"]["severity"],
)
elif data.get("status") == "resolved":
# 故障恢复时间
record_incident_resolve(
alert_id=alert["fingerprint"],
resolve_time=datetime.datetime.now(),
)
return {"status": "ok"}
第 3 步:建立度量看板
在 Grafana 中创建 MTTR/MTBF 专项看板,数据源接 Alertmanager + 自建 incident 数据库。
第 4 步:定期回顾
周度回顾:
- 本周 MTTR vs 上周 MTTR
- MTTR 分解:哪个环节最慢
- Top 3 根因分类
月度回顾:
- MTBF 趋势
- 可用性 vs SLO
- Action Items 落地情况
- 最差故障复盘
关联知识
- SRE 稳定性工程总览 — 本篇是其度量层核心
- SLO SLI 错误预算与智能告警 — SLO 定义了 MTTR 的预算
- 根因定位方法论 — MTTI 环节的方法论
- 无指责复盘与故障分析方法论 — 用 MTTR 数据驱动复盘改进
- 故障生命周期管理 — MTTR 各阶段的管理流程
- On-Call 体系与值班机制 — MTTA 环节的保障
- K8s 故障排查方法论 — MTTI 环节的实操框架
- 可观测性知识总览 — MTTD 环节的技术底座
- Metrics 与 Prometheus 实战 — 指标采集与告警
- Grafana 可视化与告警 — 度量看板
参考资源
- Google SRE Book: Service Level Objectives / Tracking Idempotent
- Google SRE Workbook: Measuring and Managing Reliability
- SLO Slides: https://sre.google/resources/sre-book-service-level-objectives/
学习时间
| 内容 | 日期 | 状态 |
|---|---|---|
| MTTR/MTBF 定义与计算 | 2026-08-03 | 完成:定义、分解、计算公式、SLO 关系 |
| 度量看板建设 | 待实践 | |
| 从数据到改进闭环 | 待实践 |
状态
- MTTR/MTBF 定义与计算公式
- MTTR 四子指标分解
- MTBF 优化手段
- SLO 与 MTTR/MTBF 的关系
- 计算代码示例
- 度量看板设计
- 实际落地度量体系