カスケード障害とメタステイブル障害の力学
なぜ過負荷が去っても障害が続くのか。小さな擾乱が正のフィードバックで自己持続する力学を解き、トリガとサステイナの分離で自力回復させる原理を掴めます。
- 1.カスケード障害はノードの脱落が残りへ負荷を再配分し連鎖脱落を呼ぶ伝播現象。メタステイブル障害は擾乱が去っても自己強化ループが続き低スループットに張り付く準安定現象で、両者は重なり合う。
- 2.中核機構はリトライ増幅と容量退化。再送が無効仕事を増やし、無効仕事がレイテンシを伸ばし、それがさらに再送を呼ぶ正のフィードバックが燃料を自給する。
- 3.回復はトリガ(引き金)とサステイナ(持続要因)の分離が鍵。負荷を戻すだけでは不十分で、流入遮断・キューパージ・予算付き再送でサステイナのループ利得を1未満へ落とす介入が要る。
なぜ過負荷が去っても障害が続くのか
運用で最も不可解な障害は、原因がとうに消えたのに直らない 種類のものです。一瞬の負荷スパイク、短いネットワーク瞬断、デプロイ直後のキャッシュ空——引き金そのものは数秒で去った。なのにシステムは低スループットに張り付き、CPU やメモリに余裕が見えてもスループットだけが戻らない。再起動すると嘘のように直る。
この挙動の背後には二つの異なる、しかし絡み合う力学があります。カスケード障害(cascading failure) と メタステイブル障害(metastable failure) です。前者は障害が空間的に伝播する現象、後者は障害が時間的に自己持続する現象。本記事ではそれぞれの機構を分離して捉え、両者を貫く リトライ増幅 と 容量退化 という共通エンジンを明らかにし、最後に トリガとサステイナの分離 がなぜ回復の鍵になるのかを原理から解きほぐします。
カスケード障害:負荷再配分の連鎖
カスケード障害は、ある構成要素の脱落が、その負荷を残りの要素へ押し付け、押し付けられた要素が今度は過負荷で脱落し……という 負荷再配分の連鎖 です。送電網のブラックアウトと同じ構造で、分散システムでは典型的に次の形をとります。
1. N台のサーバーで合計負荷 Q を分担(1台あたり Q/N)
2. 1台が過負荷・OOM・デプロイで脱落 → 残り N-1 台へ再配分
3. 1台あたりの負荷が Q/(N-1) へ上昇
4. もともと余裕が薄ければ、この上昇で次の1台が閾値超え → 脱落
5. 残りはさらに少数で同じ Q を捌く → 3へ(雪崩式に加速)
決定的なのは、残存台数が減るほど1台あたりの負荷上昇が急峻になる 点です。Q/(N-1) と Q/(N-2) の差は N が小さいほど大きい。つまり連鎖は終盤に加速し、最後の数台が一気に飛びます。ヘルスチェックが過負荷ノードを「不健全」と判定して切り離す仕組みは、健全時には有効ですが、全ノードが等しく過負荷の局面では 生きているノードを次々に外して残りへ負荷を集中させる 加速装置に転じます。
脱落ノードを自動再起動して列に戻すと、コールドスタート の最中に通常負荷を浴びます。キャッシュ未加熱・コネクションプール未確立の状態では1リクエストあたりのコストが数倍に膨らみ、戻ってきた直後に再び脱落する。これが続くとクラスタは「再起動→コールド過負荷→再脱落」を繰り返し、復旧操作そのものがサステイナ になります。投入は段階的(ramp-up)に、温まるまで本番負荷から保護するのが鉄則です。
メタステイブル障害:二つの安定点
メタステイブル障害は、系が 二つの安定点を持つ ことから生まれます。一つは「健全な高スループット状態」、もう一つは「崩壊した低スループット状態」。平時は前者で安定していますが、十分な大きさの擾乱(トリガ)が系を後者の引力圏へ突き落とすと、トリガが消えても後者で安定し続ける。これが「メタ(準)」安定の意味で、見かけ上は安定だが本来戻るべき状態ではない、という状況を指します。
ボールが二つの窪みを持つ地形を転がる比喩が分かりやすい。浅い窪み(健全)と深い窪み(崩壊)の間に丘があり、平時はボールが浅い窪みにいる。強い一撃で丘を越えて深い窪みに落ちると、力を抜いてもボールは深い窪みに留まる。引き戻すには丘を越える分の 能動的なエネルギー注入 が要る——ここでは流入遮断やキューパージといった介入がそれにあたります。
カスケード障害との違いはこうです。カスケードは 空間的(ノードからノードへ伝播)、メタステイブルは 時間的(同じ系が時間をまたいで自己持続)。そして両者はしばしば同時に起きます。カスケードで容量が落ちた系が、メタステイブルなループに捕まって戻れなくなる——これが「一部障害から全面障害へ、そして長時間の張り付き」という典型的な大規模インシデントの骨格です。
共通エンジン1:リトライ増幅
両現象を駆動する第一のエンジンが リトライ増幅(retry amplification) です。下流が遅延・失敗すると、上流のクライアントは再送します。問題は、再送が すでに飽和した下流へさらなる流入 を加える点にあります。
増幅率は素朴には再試行回数の関数です。各層が最大 r 回再試行すると、L 層を貫く呼び出しでは最悪 r^L 倍の負荷が末端にかかり得ます。3層でそれぞれ3回なら 3^3 = 27 倍。健全時はめったに再試行が起きないのでこの上限は顕在化しませんが、下流が一度詰まると全層が一斉に再試行モードに入り、増幅率が跳ね上がります。
正常時 : 失敗率ほぼ0 → 実効負荷 ≈ ベース負荷(増幅は休眠)
過負荷 : 失敗率上昇 → 全層が再試行 → 実効負荷 = ベース × 増幅率
増幅された負荷がさらに失敗率を上げる → 増幅率がさらに上がる
= 正のフィードバック(ループ利得 > 1)
肝は、再送が生む仕事の多くが 無効仕事(dead work) だという点です。クライアントがタイムアウトした後に下流が返す応答は、誰も受け取らない。下流はその無効な応答を作るために資源を使い、その消費がさらにレイテンシを伸ばし、さらなるタイムアウトと再送を呼ぶ。x 倍の流入が x 倍より大きいレイテンシ悪化を生むと、ループ利得が1を超えて自己強化が始まります。対策は 再試行予算(一定割合を超える再送を禁ずる)と ジッタ付き指数バックオフ で増幅率を有界化することです(/devops/retry-backoff-jitter/)。
共通エンジン2:容量退化
第二のエンジンが 容量退化(capacity degradation) です。過負荷状態では、系が同じ資源で捌ける有効スループットそのものが落ちます。容量は固定ではなく、負荷の状態に依存して 動的に縮む。
退化の源は複数あります。深いキューに溜まった仕事は処理される頃にはタイムアウト済みで無効仕事になる(/devops/queueing-theory-tail-latency/ の 1/(1−ρ) でテイルが発散する話と地続き)。GC 圧やコンテキストスイッチ増大でオーバーヘッドが膨らむ。コネクションプールが枯渇して待ちが連鎖する。キャッシュが過負荷でヒット率を落とし、1リクエストあたりのバックエンド呼び出しが増える。
健全時 : 容量 C_high(キャッシュ温・キュー浅・GC余裕あり)
擾乱後 : 容量 C_low へ退化(キャッシュ冷・キュー深・無効仕事が資源を占有)
→ C_low < 現在の到着率 なら、負荷を平時水準へ戻しても
まだ C_low では捌けず、退化状態が維持される(張り付き)
ここに張り付きの正体があります。健全な容量 C_high なら平時負荷を楽に捌けるのに、いったん C_low へ退化すると、平時負荷が退化容量を上回ったまま になり、ループが回り続ける。負荷を「障害前と同じ水準」へ戻しても、その水準が C_low を超えていれば回復しません。容量が C_high へ戻るには、キャッシュ再加熱やキューパージで退化要因を先に取り除く必要があります。
過負荷ノードがヘルスチェックに断続的に落ちると、ロードバランサが出し入れを繰り返す(フラッピング)。外された瞬間に他ノードへ負荷集中(カスケード)、戻った瞬間にコールド過負荷で再脱落(容量退化)、その間クライアントは再試行(リトライ増幅)。三つのエンジンが噛み合い、系は崩壊状態でロックします。ヘルスチェックには十分なヒステリシスを持たせ、過負荷と故障を区別することが要点です。
トリガとサステイナの分離
ここまでの力学が示す最重要の実務原則が、トリガ(引き金)とサステイナ(持続要因)の分離 です。診断で最も多い誤りが、両者の混同です。
| トリガ | サステイナ | |
|---|---|---|
| 役割 | 系を崩壊の引力圏へ突き落とす一撃 | 崩壊状態を自己維持するループ |
| 例 | 負荷スパイク・瞬断・デプロイ・キャッシュ空 | リトライ増幅・無効仕事・容量退化・フラッピング |
| 持続時間 | 短い(去ることが多い) | トリガ消失後も続く |
| 回復への寄与 | 取り除いても回復しない | 断てば回復する |
「原因のスパイクは収まったのに直らない」という現象は、トリガはとうに去り、サステイナだけが回り続けている ことを意味します。したがって復旧の対象はトリガではなくサステイナです。やるべきは、サステイナの ループ利得を1未満へ落とす 介入です。
- 流入を一時遮断する:負荷遮断(429/503)でループから燃料を抜き、退化容量でも捌ける水準まで到着率を下げる。回復したら段階的に開放する。
- キューを能動的にパージする:滞留してすでに無効な仕事を実行前に捨て、無効仕事への資源浪費を止める。デッドラインを下流へ伝播させる。
- 再試行を予算で縛る:再試行予算とサーキットブレーカで増幅率を強制的に有界化する(/devops/circuit-breaker-bulkhead/)。
- 温めてから戻す:再投入ノードはキャッシュ再加熱まで本番負荷から保護し、コールド過負荷の再脱落を防ぐ。
メタステイブル障害は 自動復旧を前提にできない。負荷が引いても戻らない以上、Runbook には「サステイナを断つ手順」を明記する。設計段階では、ループ利得が1を超えないよう構造で封じる——有界キュー・予算付き再送・適応的同時実行制限・負荷遮断を入口に置く。二つの安定点の存在は障害注入で能動的に検証するのが上級者の作法(/devops/chaos-engineering/)。SLO とエラーバジェットは、崩壊への余裕がどれだけ残っているかの先行指標になる(/devops/sre-slo/)。
まとめ
- カスケード障害 は脱落ノードの負荷が残りへ再配分され連鎖脱落を呼ぶ 空間的 伝播。残存台数が減るほど加速し終盤で雪崩る。
- メタステイブル障害 は系が持つ二つの安定点のうち崩壊側へ落ちると、トリガが消えても自己持続する 時間的 な張り付き。両者はしばしば同時に起きる。
- 共通エンジンは リトライ増幅(無効仕事を増やす正のフィードバック、最悪
r^L倍)と 容量退化(退化容量C_lowが平時負荷を下回り張り付く)。 - 回復の鍵は トリガとサステイナの分離。負荷を戻すだけでは不十分で、流入遮断・キューパージ・予算付き再送・段階再投入でサステイナのループ利得を1未満へ落とす能動介入が要る。
- 設計では構造でループ利得を封じ、二安定性を障害注入で検証し、Runbook にサステイナを断つ手順を残す。
DevOps/インフラ Article
カスケード障害とメタステイブル障害の力学を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
カスケード障害
比較で見る軸
難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 6
導入後に効く点
中核機構はリトライ増幅と容量退化。再送が無効仕事を増やし、無効仕事がレイテンシを伸ばし、それがさらに再送を呼ぶ正のフィードバックが燃料を自給する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- DevOps/インフラ
- タグ数
- 6
判断チェックリスト
- 自社の用途が「カスケード障害 / メタステイブル障害」に近いか確認する。
- 強みである「カスケード障害はノードの脱落が残りへ負荷を再配分し連鎖脱落を呼ぶ伝播現象。メタステイブル障害は擾乱が去っても自己強化ループが続き低スループットに張り付く準安定現象で、両者は重なり合う。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。