ストーリー
佐藤CTOはホワイトボードにタイムラインを描き始めました。
信頼性メトリクス:MTBF / MTTR / MTTD
信頼性を定量的に評価するための主要メトリクスを理解しましょう。
メトリクスの全体像
graph LR
A["障害発生"] --> B["検知<br/>(MTTD)"] --> C["対応開始<br/>(MTTA)"] --> D["復旧完了<br/>(MTTR)"] --> E["正常稼働期間"] --> F["次の障害発生"]
A -.->|"MTBF(障害間の平均時間)"| F
各メトリクスの定義
| メトリクス | 正式名称 | 定義 | 理想的な方向 |
|---|---|---|---|
| MTBF | Mean Time Between Failures | 障害と障害の間の平均時間 | 長いほど良い |
| MTTD | Mean Time To Detect | 障害発生から検知までの平均時間 | 短いほど良い |
| MTTA | Mean Time To Acknowledge | 障害発生から対応開始までの平均時間 | 短いほど良い |
| MTTR | Mean Time To Recovery | 障害発生から復旧完了までの平均時間 | 短いほど良い |
メトリクスの計算例
interface Incident {
id: string;
occurredAt: Date; // 障害発生時刻
detectedAt: Date; // 検知時刻
acknowledgedAt: Date; // 対応開始時刻
resolvedAt: Date; // 復旧完了時刻
}
function calculateReliabilityMetrics(incidents: Incident[]) {
const sorted = incidents.sort(
(a, b) => a.occurredAt.getTime() - b.occurredAt.getTime()
);
// MTTD: 検知までの平均時間
const mttd =
sorted.reduce((sum, inc) => {
return sum + (inc.detectedAt.getTime() - inc.occurredAt.getTime());
}, 0) / sorted.length;
// MTTA: 対応開始までの平均時間
const mtta =
sorted.reduce((sum, inc) => {
return sum + (inc.acknowledgedAt.getTime() - inc.occurredAt.getTime());
}, 0) / sorted.length;
// MTTR: 復旧までの平均時間
const mttr =
sorted.reduce((sum, inc) => {
return sum + (inc.resolvedAt.getTime() - inc.occurredAt.getTime());
}, 0) / sorted.length;
// MTBF: 障害間の平均時間
let mtbf = 0;
if (sorted.length > 1) {
const intervals = sorted.slice(1).map((inc, i) => {
return inc.occurredAt.getTime() - sorted[i].occurvedAt.getTime();
});
mtbf = intervals.reduce((sum, v) => sum + v, 0) / intervals.length;
}
return {
mttd: mttd / (1000 * 60), // 分単位
mtta: mtta / (1000 * 60),
mttr: mttr / (1000 * 60),
mtbf: mtbf / (1000 * 60 * 60), // 時間単位
};
}
MTTRの改善戦略
| 改善対象 | 手法 | 効果 |
|---|---|---|
| MTTD(検知時間) | アラート閾値の最適化、合成監視 | 障害を素早く発見 |
| MTTA(応答時間) | オンコール体制、PagerDuty連携 | 対応者を素早くアサイン |
| 診断時間 | ランブック整備、ダッシュボード | 原因を素早く特定 |
| 修復時間 | 自動復旧、ロールバック自動化 | 修復を素早く完了 |
可用性のNines(9の数)
可用性の計算
可用性は以下の公式で計算されます。
可用性 = 稼働時間 / (稼働時間 + ダウンタイム) × 100%
または
可用性 = MTBF / (MTBF + MTTR) × 100%
Ninesテーブル
| 可用性 | Nines | 年間ダウンタイム | 月間ダウンタイム | 週間ダウンタイム |
|---|---|---|---|---|
| 90% | One Nine | 36.5日 | 72時間 | 16.8時間 |
| 99% | Two Nines | 3.65日 | 7.2時間 | 1.68時間 |
| 99.9% | Three Nines | 8.76時間 | 43.2分 | 10.1分 |
| 99.95% | Three and a half | 4.38時間 | 21.6分 | 5.04分 |
| 99.99% | Four Nines | 52.6分 | 4.32分 | 1.01分 |
| 99.999% | Five Nines | 5.26分 | 25.9秒 | 6.05秒 |
Ninesの「壁」
xychart-beta
title "可用性とコストの関係(各Nineで約10倍増)"
x-axis ["99%", "99.9%", "99.99%", "99.999%"]
y-axis "コスト(相対)" 0 --> 1100
line [1, 10, 100, 1000]
コンポーネントの可用性計算
システム全体の可用性は、最も弱いコンポーネントに引きずられます。
// 直列構成: 全コンポーネントが稼働する必要がある
function serialAvailability(components: number[]): number {
return components.reduce((acc, avail) => acc * avail, 1);
}
// 並列構成(冗長化): どれか1つが稼働していればよい
function parallelAvailability(components: number[]): number {
const unavailability = components.reduce(
(acc, avail) => acc * (1 - avail),
1
);
return 1 - unavailability;
}
// 例: Webサーバー(99.9%) → API(99.9%) → DB(99.9%)の直列構成
const serialResult = serialAvailability([0.999, 0.999, 0.999]);
// 結果: 0.997 = 99.7%(Three Ninesが維持できない!)
// 例: DB を2台で冗長化(各99.9%)
const dbRedundant = parallelAvailability([0.999, 0.999]);
// 結果: 0.999999 = 99.9999%
// 冗長化DBを使った直列構成
const improvedResult = serialAvailability([0.999, 0.999, dbRedundant]);
// 結果: 0.998 = 99.8%
実サービスの可用性目標の例
| サービス | 公表SLA | Nines |
|---|---|---|
| AWS EC2 | 99.99% | Four Nines |
| AWS S3 | 99.99% | Four Nines |
| AWS RDS (Multi-AZ) | 99.95% | Three and a half |
| Google Cloud Compute | 99.99% | Four Nines |
| Azure Virtual Machines | 99.99% | Four Nines |
| Stripe API | 99.99% | Four Nines |
注意: クラウドプロバイダのSLAは「リージョン内の冗長構成」が前提です。単一インスタンスでの可用性はこれより低くなります。
ダウンタイムのコスト
信頼性の投資判断を行うには、ダウンタイムの事業コストを理解する必要があります。
ダウンタイムコストの計算
interface DowntimeCostModel {
revenuePerHour: number; // 時間あたりの売上
employeeCostPerHour: number; // 影響を受ける従業員の時間あたりコスト
affectedEmployees: number; // 影響を受ける従業員数
reputationMultiplier: number; // ブランド毀損係数(1.0〜3.0)
slaViolationCost: number; // SLA違反時のペナルティ/時間
}
function calculateDowntimeCost(
model: DowntimeCostModel,
downtimeHours: number
): {
revenueLoss: number;
productivityLoss: number;
reputationCost: number;
slaPenalty: number;
totalCost: number;
} {
const revenueLoss = model.revenuePerHour * downtimeHours;
const productivityLoss =
model.employeeCostPerHour * model.affectedEmployees * downtimeHours;
const reputationCost =
revenueLoss * (model.reputationMultiplier - 1);
const slaPenalty = model.slaViolationCost * downtimeHours;
return {
revenueLoss,
productivityLoss,
reputationCost,
slaPenalty,
totalCost: revenueLoss + productivityLoss + reputationCost + slaPenalty,
};
}
// 例: ECサイトの1時間ダウンタイムコスト
const ecSite: DowntimeCostModel = {
revenuePerHour: 500_000, // 時間あたり50万円の売上
employeeCostPerHour: 5_000, // 1人あたり5,000円/時間
affectedEmployees: 20, // 20名の従業員に影響
reputationMultiplier: 1.5, // ブランド毀損50%
slaViolationCost: 100_000, // SLA違反ペナルティ10万円/時間
};
const cost = calculateDowntimeCost(ecSite, 1);
// revenueLoss: 500,000円
// productivityLoss: 100,000円
// reputationCost: 250,000円
// slaPenalty: 100,000円
// totalCost: 950,000円 (1時間で約95万円の損失)
可用性レベルごとのコスト比較
| 可用性 | 年間ダウンタイム | 年間コスト(上記モデル) | 追加投資目安 |
|---|---|---|---|
| 99% | 87.6時間 | 約8,300万円 | ベースライン |
| 99.9% | 8.76時間 | 約830万円 | +数百万円/年 |
| 99.95% | 4.38時間 | 約416万円 | +数千万円/年 |
| 99.99% | 52.6分 | 約83万円 | +数億円/年 |
「この数字を見れば、どこまでの可用性に投資すべきかが判断できる。99.9%から99.99%への改善に年間数億円かける価値があるかは、ビジネスの規模と性質次第だ」 — 佐藤CTO
信頼性の設計原則
Failure is Inevitable(障害は必ず起きる)
graph TD
T["<b>信頼性の設計原則</b>"]
P1["1. Design for Failure(障害前提設計)<br/>障害は「もし」ではなく「いつ」の問題"]
P2["2. Defense in Depth(多層防御)<br/>単一の防御策に頼らない"]
P3["3. Graceful Degradation(優雅な劣化)<br/>全部落とすより一部を維持する"]
P4["4. Blast Radius Reduction(影響範囲縮小)<br/>障害の影響を限定的に抑える"]
P5["5. Automation First(自動化優先)<br/>人間の判断を減らし、復旧を自動化する"]
T --> P1
T --> P2
T --> P3
T --> P4
T --> P5
style T fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
Graceful Degradation の実装例
interface ServiceResponse<T> {
data: T | null;
degraded: boolean;
fallbackUsed: boolean;
source: 'primary' | 'cache' | 'fallback';
}
class ResilientProductService {
constructor(
private primaryDb: Database,
private cache: CacheStore,
private fallbackData: FallbackProvider,
) {}
async getProduct(id: string): Promise<ServiceResponse<Product>> {
// 1. まずプライマリDBを試行
try {
const product = await this.primaryDb.findProduct(id);
await this.cache.set(`product:${id}`, product, 300); // 5分キャッシュ
return {
data: product,
degraded: false,
fallbackUsed: false,
source: 'primary',
};
} catch (primaryError) {
console.warn(`Primary DB failed for product ${id}:`, primaryError);
}
// 2. キャッシュにフォールバック
try {
const cached = await this.cache.get<Product>(`product:${id}`);
if (cached) {
return {
data: cached,
degraded: true,
fallbackUsed: false,
source: 'cache',
};
}
} catch (cacheError) {
console.warn(`Cache failed for product ${id}:`, cacheError);
}
// 3. 最終フォールバック(静的データ)
try {
const fallback = await this.fallbackData.getProduct(id);
return {
data: fallback,
degraded: true,
fallbackUsed: true,
source: 'fallback',
};
} catch {
return {
data: null,
degraded: true,
fallbackUsed: true,
source: 'fallback',
};
}
}
}
まとめ
| ポイント | 内容 |
|---|---|
| MTBF/MTTR/MTTD | 信頼性を定量的に測定する基本メトリクス |
| 可用性のNines | 99.9%と99.99%の差は約8時間 vs 53分(年間ダウンタイム) |
| コンポーネント計算 | 直列構成では可用性が掛け算で低下、冗長化で改善 |
| ダウンタイムコスト | 事業コストを算出して適切な投資判断を行う |
| 設計原則 | 障害前提設計、多層防御、優雅な劣化 |
チェックリスト
- MTBF/MTTR/MTTDの定義と計算方法を理解した
- 可用性のNinesテーブルを説明できる
- コンポーネントの直列・並列構成の可用性計算ができる
- ダウンタイムのビジネスコストを見積もれる
- 信頼性の設計原則(障害前提設計、Graceful Degradation)を理解した
次のステップへ
次は「エラーバジェットの考え方」を学びます。100%の信頼性を目指さない — SREの最も革新的な概念であるエラーバジェットの仕組みと活用方法を深掘りしましょう。
推定読了時間: 30分