何が起きたか
2010年9月、Facebookは約2時間半にわたってダウンした。ソフトウェアエンジニアリング担当ディレクターのRobert Johnson氏が同日に公開した異例の公式ポストモーテムで、同社のエンジニアリングチームはこれを4年以上の間にサイトが経験した最悪の障害と評した。サイトが復旧するまで、すべてのページで、すべての訪問者がエラーに遭遇した。
根本原因は、設定値を健全に保つための自動システムだった。これはキャッシュされた値を永続ストアと比較し、無効と判断したものを置き換えるものだった。その日、ある変更によって永続ストア自体に不正な値が残された。すべてのクライアントがその「無効な」値を目にし、修復しようとした。修復とはデータベースクラスタへの問い合わせを意味したため、クラスタには毎秒数十万件のクエリが殺到した。
エラー処理が事態をさらに悪化させた。クライアントのクエリが失敗すると、その失敗を「値は依然として無効」と解釈し、該当するキャッシュキーを削除した。これが新たな修復クエリを生み出した。元の不正な値が修正された後も、ループは自らを養い続けた。脱出する唯一の方法はデータベースクラスタへの全トラフィックを停止することであり、それはサイトを完全に停止し、データベースを復旧させ、その後ユーザーを徐々に戻すことを意味した。
何を犠牲にしたか
サイト全体が約2.5時間ダウン — Facebookのエンジニア自身が4年以上で最悪の障害と評した
なぜ起きたか
検証ツールは永続ストアが常に正しいと仮定していた。永続ストアが不正な値を持つと、すべてのクライアントが同じ汚染された修復指示を受け取った。
エラー処理が「データベースの過負荷」と「無効な値」を混同したため、失敗するたびに負荷が増大し、増幅するフィードバックループとなった。
エラー時にキャッシュキーを削除したことで、リトライの嵐を吸収し得た唯一の層が失われた。
クライアントとクラスタの間にサーキットブレーカーがなく、残された唯一の手段はサイトの完全停止だった。
教訓
あらゆるエラーを「直しに行け」と扱う自己修復コードは、障害を吸収するどころか増幅させる。クライアントごとのリトライを制限し、フィードバックループを減衰させ、完全停止に至る手前で使える復旧手段を用意しておくべきだ。
その後
Facebookは同日中に自己修正型設定システムを停止し、一時的な急増やフィードバックループを許容するパターンを中心に再設計すると述べた。サービスは同日中に完全復旧し、当時世界最大のソーシャルネットワークだった同社は数時間以内に技術的詳細を公開した。このインシデントは、小さな障害を自己持続的な嵐に変えてしまうエラー処理の教科書的な事例として今も引用されている。
出典をたどる
出典
- More Details on Today's Outage Facebook Engineering (Wayback Machine snapshot of the original note) · web.archive.org ·
- How Facebook fixed the site: they turned it off and on again. Literally The Guardian · theguardian.com ·
- Massive Facebook outage caused by improper error handling, not improper Facebook flirting as previously feared Engadget · engadget.com ·