学ぶべき3つの失敗コンセプト
おかえり
分散システムはパターンで失敗します。パターンを学ぶと、ポストモーテムはすべての認識演習になる代わりに謎ではなくなる。
3つの概念がほとんどのものの生産的な失敗解析に必要です:
単一点の失敗 (SPOF): 一つのコンポーネントの失敗がより大きなシステムをダウンさせるもの。しばしば隠れています: すべてに依存しているDNSサーバー; すべてが更新する対象の単一の証明書; 一つのデータベースマスター。
連鎖的な失敗: 一つのコンポーネントの失敗が他の一つを引き起こし、それが他の一つを引き起こす。スローダータベースはAPIレイヤーのタイムアウトを引き起こし、それがリトライを引き起こし、それがロードをさらに増やすことを引き起こし、より多くのタイムアウトを引き起こす。爆発は広がります。
爆発半径: 一つのピースが失敗したときにどれだけ多くのシステムがダウンするか。建築的選択は爆発半径を制限するか、制限しないかのどちらかです。SPOFは制限されていない爆発半径を持っています。バルクヘッドされたサービスは制限された半径を持っています。
このレッスンの終わりに達すると:
- 架構を検査することでSPOFを特定できます
- 連鎖的な失敗パターンを認識: サンダーイングヘルド、リトライストーム、キューの死
- 実際のタイムラインを読み、トリガーが潜在的な欠陥を表面化させたものと区別できます
- 人ではなくシステムをターゲットにした無責任なアクション項目を書くことができます、予防 / 検出 / 復旧をカバー
- バルクヘッドとサーキットブレーカーを爆発半径を制限するツールとして推理できます
SPOFを見つけ出す
層別アーキテクチャの検査
小規模なWebアーキテクチャを考慮してください:
- DNS: api.example.com -> 一つの名前サーバーIP 203.0.113.10 一つのDNSプロバイダーにホストされている
- CDN: 一つのCDNベンダーがapi.example.comの前にある
- 侵入: 二つのリバースプロキシマシンがロードバランサー後ろにあり
- バックエンド: 二つの可用性ゾーン(それぞれ3つ)に6つのAPIレプリカがあり
- データベース: 一つのプライマリ+一つのリードレプリカ、同じ可用性ゾーンにあり
- キャッシュ: リディスクラスター、3ノードが同じ2つの可用性ゾーンに分散され
質問: SPOFはどのコンポーネントですか?ヒント: SPOFは常に明確な'一つのマシン'タイプではありません。同じ可用性ゾーンにある3つのマシンは、ゾーンの失敗のためのSPOFです。
三个经典级联模式
失效通过依赖关系传播
模式1:雷鸣群。 一个共享资源(缓存、锁定、数据库)失败或重新启动。依赖于它的每个客户端同时重试。洪峰淹没了恢复;重试比恢复更快地堆积;恢复永远无法完成。
模式2:重试风暴。 下游服务变慢。上游调用者,而不是失败,重试。重试乘以了原始负载。服务变慢,触发更多重试。最终负载超过了服务的健康版本。
模式3:死亡队列。 无背压的处理队列比它处理得更快。队列无限增长。内存耗尽;消费者崩溃;重新启动;发现一个更大的队列;再次崩溃。
共同点: 一个小的初始扰动触发了正反馈循环。系统的响应放大了失败,而不是减小。
减小机制
指数退避与抖动。 等待重试的客户端每次等待的时间更长,带有随机偏移。防止同步重试波浪。
断路器。 调用者跟踪下游故障率。超过阈值,调用者停止调用,进入cool down期,并立即失败自己的请求。防止浪费工作,让下游恢复。
隔舱。 为每个依赖分隔资源。连接池A用于数据库,连接池B用于缓存。一个慢数据库不能挤压所有连接;缓存调用继续。
负载降级。 当过载时,在边缘处丢弃请求,而不是接受并慢慢失败。1毫秒内的429比30秒内的500好。
背压。 当消费者无法跟上时,慢速生产者。队列变为有界;发送者阻塞;原始工作来源感受到摩擦。
诊断级联
チームのAPI層が定期的なデータベースフェイルオーバーの間で溶解します。タイムライン:
- 14:00:00 — 操作者がスタンバイデータベースを促進します。予想される無効期間:約10秒。
- 14:00:08 — 主データベースが利用不能になります。API層でデータベース接続エラーが始まります。
- 14:00:08 — API層がリトライ(デフォルト構成:5回のリトライ、リトライなし、100ms間隔)。
- 14:00:11 — スタンバイが促進され、新しい接続を受け入れます。
- 14:00:11 — API層が同時に新しいデータベース接続を開きます(各レプリカx各並行リクエストx各リトライ)。
- 14:00:13 — 新しいプライマリの接続プールが枯渇し、新しい接続が拒否されます。
- 14:00:13-14:05:00 — API層のレプリカが接続プールを枯渇し、例外をスローし、再起動し、繰り返します。
- 14:05:00 — 操作者がAPI層のトラフィックを手動で停止し、データベースが安定します。
- 14:10:00 — 減少したトラフィックの復旧が完了します。総ダウンアウト:約10分(予想:約10秒)。
DNS SERVFAIL: Two Compounding Defects
A Real-Shape Postmortem
以下は、実際のインシデントのサニタ化されたバージョンです。ベンダー名が変更され、IPが匿名化されますが、形状、タイムライン、そしてレッスンはすべて現実です。
Summary
サイトexample.comは約3-4時間、すべてのパブリックDNSリゾルバーからSERVFAILを返しました。同一DNSマスタ上の他の46つのゾーンは影響を受けませんでした。原因:2つの複合した欠陥がありました。
1. Vendor A(セカンダリDNSプロバイダー)がプライマリのallow-axfr-ips許可リストに含まれていない新しい内部同期IPを追加しました。
2. example.comゾーンが、RFCに違反するCNAME競合がありました(demo.example.comは同じラベルでCNAMEおよびMX/TXTレコードがありました)。これがVendor Aが新しいAXFRを拒否する原因となりました。
Timeline (UTC)
- ~15:00 — Vendor Aがインフラストラクチャに新しい同期IP 198.51.100.42を追加しました
- 15:02 — first AXFR-out denied for 198.51.100.42 appears in primary DNS logs (no alerting on this signal)
- ~18:00 — SOA expire window reached; Vendor A drops example.com zone from cache
- ~18:30 — SERVFAIL detected externally
- ~19:45 — root cause identified
- 20:00 — 198.51.100.42 added to allow-axfr-ips; primary restarted
- 20:05 — NOTIFY sent; AXFR initiated; zone STILL SERVFAIL (CNAME conflict)
- 20:07 — check-zone reveals 1 error: CNAME conflict on demo.example.com
- 20:09 — CNAME replaced with A record; zone check clean (0 errors)
- 20:10 — NOTIFY sent; AXFR completes; Vendor A begins serving zone
- 20:11 — dig @8.8.8.8 example.com A returns correct IP — RESOLVED
Why Only example.com?
All 47 zones share the same DNS primary. The AXFR IP block affected all zones. But only example.com had the CNAME conflict, & only example.com needed a fresh AXFR at the moment the deny was enforced. Other zones had already refreshed before the deny or did not yet need to.
Latent defect
The CNAME conflict at demo.example.com had existed for years. It worked because the primary served the zone from its database (lenient about RFC violations) & Vendor A was serving from stale cached data from before the violation was introduced. When Vendor A dropped its cache & needed fresh data, the violation surfaced.
Trigger
Vendor A silently added a new sync IP. The primary's allowlist did not include it. AXFR denied. Three hours later (SOA expire), Vendor A dropped the zone. The latent defect surfaced when the system tried to recover.
Write Blameless Action Items
Blameless: Target Systems, Not People
A blameless action item names something the system should do differently, not something a person should do differently. 'Train the operator' is blameful. 'Add an automated check that catches this before deploy' is blameless.
Good blameless action items cluster into three dimensions:
- Prevention: make the bad thing harder or impossible
- Detection: notice it sooner if it happens
- Recovery: limit the damage when it happens
Each item should name (1) the specific system change, (2) an owner team, & (3) the dimension it serves.
船が沈まないように沈むことのない compartments
海軍工学から借りる
船は水密隔壁を持っています:垂直な壁が船体を compartments に分割します。一つの compartments が浸水しても船が沈まない、一つの compartments が機能しなっても他のものに影響を与えません。
分散システムは同じ言葉と同じアイデアを借りています。
水密隔壁パターン:依存関係ごとにリソースを分離します。3つのダウンストリーム API を呼び出すサービスは、3つの独立した接続プール、3つの独立したスレッドプール、3つの独立したリトライ予算を持っています。一つのダウンストリームが遅くなったり失敗したりすると、他の2つには影響を与えません。
水密隔壁なし:一つの遅い依存関係が共有スレッドプールを枯渇すると、他の依存関係の呼び出しもスレッドを待機しているうちにブロックされ、全体のサービスが応答不能になります。
水密隔壁あり:一つの遅い依存関係が自分のプールを枯渇すると、呼び出しはすぐに失敗します。他の依存関係の呼び出しは通常通り続けられ、失敗した依存関係に影響を与える範囲を制限されます。
回路ブレーカーパターン
回路ブレーカーパターン:ダウンストリーム依存関係のラッパで、失敗率を追跡する状態があります。3つの状態があります。
- 閉じた(通常):呼び出しが通じます。失敗がカウントされます。
- 開いた(トリップ):過去の失敗閾値(例えば、過去30秒で50%の失敗)に達するとブレーカーが開きます。呼び出しは失敗し、依存関係に負荷を与えずに健康状態が悪い場合に無駄な労力を防ぎます。
- 半開き(テスト):クールダウン期間が終わったら、ブレーカーは少量の呼び出しを許可します。成功した場合、通常に戻ります。失敗した場合、再度開くためにクールダウンします。
鍵の見解:回路ブレーカーは、不健康な期間中に無駄な労力を防ぎ、ダウンストリームに回復のチャンスを与え、継続的な負荷を与えずにダウンストリームが回復できるようにします。
水密隔壁は爆発半径を制限し、回路ブレーカーは爆発が持続するのを防ぎます。
爆発半径を制限する
APIサービスは、ユーザーサービス、レコメンデーションサービス、通知サービス、および第三者Payment APIを下流サービス4つを呼び出します。チームは、レコメンデーションサービスが少し不安定であると聞いており、問題が発生した場合でもシステム全体が健康的に維持されることを確認したいと考えています。
現在、このサービスは1つの共有スレッドプール(200スレッド)と1つの共有HTTP接続プールを使用しています。下流のすべての4つは、これらのリソースを競争します。サーキットブレーカーはありません。
失敗モードレビューのデザイン
合成
失敗を検出するスキルを身につけました。ポストモーテムを読み、トリガーと潜在的な欠陥を区別することができます。防御 / 検出 / 復旧の3つの領域で非難のないアクションアイテムを書くことができ、Bulkheads + Circuit Breakers + Graceful Degradationでblast radiusを制限することができます。
すべての5つを適用してください。
チームは、新しいサービスsearch.example.comをリリースする前に、3つの下流サービスに依存する検索サービスを指揮することを望んでいます:主な検索インデックス(index.example.com)、分析サービス(analytics.example.com)、およびレコメンデーションサービス(recs.example.com)。チームはあなたにリリース前に失敗モードレビューを指揮するよう求めています。
このコースが次にどこへ行くか
このコースが次にどこへ行くか
失敗を検出することができ、キャスケードを認識し、ポストモーテムを効果的に読み、非難のないアクションアイテムを書くことができ、設計でblast radiusを制限することができます。
このコースの最終レッスン(cs_distsys_observability_and_capacity)は、ユーザーが問題を知る前に問題が発生しているかどうかを判断するために測定すべきことを教えます。Health checks、バージョンエンドポイント、プロキシ層の四つの黄金信号、そして観察データに基づいてスルージャパシティの決定がつながる方法です。
連携レッスン: geometry_of_failure_modes_and_blast_radiusは、間接的中央性(グラフノードがボトルネックであるのはどれか)と最小カット(爆発半径の上限)を導出します。
素晴らしいです。進んでください。