---
title: 故障モデル
url: https://doc.liz6.com/ja/distributed-systems/01-basic-theory/03-fault-models
locale: ja
area: distributed-systems
tags:
- distributed-systems
- basic-theory
date: 2026-06-30
modified: 2026-07-16
description: ノードはクラッシュする可能性があり、通信不能になる可能性があり、嘘をつく可能性があります。Crash-Stop から Byzantine へ、故障モデルの每一次のアップグレードはプロトコル設計の難易度を2倍にします——そして、エンジニアリングにおいて「どのくらいのタイムアウト時間が故障とみなされるか」自体が正解のないトレードオフです：短すぎると生きているノードを誤検知し、長すぎるとシステムが空待ちになります。
---

# 故障モデル

> ノードはクラッシュする可能性があり、通信不能になる可能性があり、嘘をつく可能性があります。Crash-Stop から Byzantine へ、故障モデルの每一次のアップグレードはプロトコル設計の難易度を2倍にします——そして、エンジニアリングにおいて「どのくらいのタイムアウト時間が故障とみなされるか」自体が正解のないトレードオフです：短すぎると生きているノードを誤検知し、長すぎるとシステムが空待ちになります。

## 故障の分類

### Crash-Stop (Fail-Stop)

ノードの実行停止後、**再起動しません**。これは最も単純な故障モデルです——一度ノードがクラッシュすると、新しい出力を生成することは永久にありません。コンセンサスプロトコル（Paxos/Raft）はこのモデル下で簡潔な証明を持っています。

特徴：永続化は不要です（クラッシュ後、ノードはログの回復を必要としません）、状態はメモリに置くことができます。しかし、実務では真の crash-stop システムは極めて稀です——多くのシステムは crash-recovery を必要とします。

### Crash-Recovery

ノードは停止しますが、ある期間（任意の時間）後に**再起動して実行を再開します**。回復には、永続ストレージ（WAL/journal）からクラッシュ前の状態をリプレイする必要があります。これは最も現実的な故障モデルです——Raft/etcd は crash-recovery を対象として設計されています。

回復後の重要な課題：再起動したノードは、ログが失われていないことを**証明**できなければなりません——つまり、ログが永続的に書き込まれ、クラッシュ前に確認されている必要があります。これが Raft が `fsync` をログエントリに対して実行してからリーダーに応答する理由です。

### Byzantine (ビザンチン) 故障

ノードは**任意の動作**を行うことができます——偽メッセージの送信、選択的な応答、意図的な破壊を含みます。悪意のある攻撃だけでなく、メモリビットフリップ（宇宙線）、ファームウェアのバグ、ネットワークデバイスの誤った転送なども Byzantine 動作を引き起こす可能性があります。

Byzantine は crash よりもはるかに困難です：Paxos/Raft は `f` 個の crash を許容するために `2f+1` 個のノードで十分ですが、PBFT（Practical Byzantine Fault Tolerance）は `f` 個の Byzantine ノードを許容するために `3f+1` 個のノードを必要とします。

理由：Byzantine ノードは**誠実なノードに対して異なる情報を伝える**ことができます——誠実なノードは「相手が嘘をついている」と「ネットワークがパケットをドロップした」ことを区別できません。PBFT の 3f+1 の下限は必要であることが証明されています。

### 実践的な分布

実際のシステムでは Byzantine 耐性はほとんど必要ありません——閉じたデータセンター/クラスター内では、crash-recovery がほとんどの故障をカバーします。Byzantine は主に以下の場合に現れます：

- ブロックチェーン/暗号通貨（ノードが互いを信頼しない）
- 組織間コラボレーション（共通の信頼ルートがない）
- 極めて重要なインフラストラクチャ（Spanner は TrueTime を使用して、特定の Byzantine 的な時刻攻撃を防いでいます）

## ネットワークパーティション

パーティションはクラッシュとは異なります——ノードは稼働しており、クライアントリクエストを受け付けることができますが、他のノードとは通信できません。パーティションは CAP 定理の中核的な脅威です：**パーティション発生時、あなたは整合性か可用性かのどちらかを選ばなければなりません。**

### 対称パーティション vs 非対称パーティション

- 対称パーティション：クラスターが等しい2つの部分に分割され、それぞれがノードの過半数を持つ → (Raft を使用して) 過半数を持つ方の半分だけがリーダーを選出し、サービスを提供し続けることができる
- 非対称パーティション：単一のノードが他のすべてのノードから切断される → そのノードはリーダーになれず、ブレインシュラウド（脳分裂）も引き起こさない

### Split-Brain (ブレインシュラウド)

マルチリーダーシステム + パーティション = 2つのパーティションがそれぞれリーダーを選出 → 両方が同時に書き込みを受け入れる → パーティション回復時に競合が発生する。古典的な解決策：

- Raft/Paxos: 常に過半数のパーティションのみがリーダーを持つことができる（数学的保証）
- システムレベルの防御：STONITH (Shoot The Other Node In The Head) → 古いマスターをフェンスするか、直接電源を切る

## タイムアウト

分散システムの核心的な緊張関係：**タイムアウトが短すぎると crash の誤検知（フォールスポジティブ）になり、タイムアウトが長すぎると故障検出が遅れ（利用不可のウィンドウが増加する）。**

Raft の選挙タイムアウトはその典型です：150-300ms のランダム化により、異なる候補者が異なるタイムアウトを持つことを保証し（分割票を避けるため）、通常の RPC レイテンシをカバーするのに十分長い必要があります。

### なぜ「正しい」タイムアウトがないのか

ネットワークレイテンシはガウス分布ではありません——長い裾（テールレイテンシ）があります。p99 レイテンシが 10ms でも、p99.9 は 100ms に跳ね上がる可能性があります。timeout=100ms に設定すると、0.1% のリクエストがタイムアウトと誤検知されます。timeout=1s に設定すると、故障検出の遅延は 1s になり、その間システムは利用できません。

この問題には理論的な解決策はなく、エンジニアリングのトレードオフのみが存在します。実務では、`φ-accrual failure detector`（05章参照）を使用して、二値判断ではなく疑念レベルを出力し——アプリケーション層に「どの程度の疑念がフェイルオーバーに値するか」を決定させます。

## 参考

- **論文**: "Impossibility of Distributed Consensus with One Faulty Process" (FLP, 1985)
- **論文**: "Practical Byzantine Fault Tolerance" (Castro & Liskov, 1999)
- **論文**: "The φ Accrual Failure Detector" (Hayashibara et al, 2004)

*Keywords: crash-stop, crash-recovery, Byzantine fault, network partition, split-brain, FLP, timeout, φ-accrual*
