目次
「うちのシステムの可用性は99.9%を目指したい」と言われたとき、それが年間で何時間の停止に相当し、どこまでの冗長化が必要なのかを即答できるでしょうか。「サーバーを2台にすれば安心」と思っていたら、実はデータベースやDNS、あるいは担当者ひとりに全部が依存していた、というのはよくある話です。
この記事では、可用性の「ナインズ」を停止時間に換算する表、直列・並列構成での可用性の計算方法、単一障害点(SPOF)の洗い出し方、アクティブ/スタンバイなどの冗長化パターン、そしてコストとの釣り合いを踏まえた中小規模での現実的な優先順位を解説します。読み終える頃には、自社システムの弱点を特定し、「まずどこから冗長化すべきか」を根拠を持って説明できるようになります。
可用性の「ナインズ」を停止時間に換算する
99.9%は年間8時間46分
可用性(Availability)とは、ある期間のうちシステムが正常に使えた時間の割合です。「9がいくつ並ぶか」でナインズ(nines)と呼ばれ、9がひとつ増えるごとに許容停止時間は10分の1になります。
| 可用性 | 通称 | 年間停止時間 | 月間停止時間 | 週間停止時間 |
|---|---|---|---|---|
| 99% | ツーナインズ | 3日15時間36分 | 約7時間18分 | 約1時間41分 |
| 99.9% | スリーナインズ | 8時間46分 | 約43分50秒 | 約10分5秒 |
| 99.95% | — | 4時間23分 | 約21分55秒 | 約5分3秒 |
| 99.99% | フォーナインズ | 52分36秒 | 約4分23秒 | 約1分1秒 |
| 99.999% | ファイブナインズ | 5分16秒 | 約26秒 | 約6秒 |
この表で意識してほしいのは、99.9%と99.99%の間にある「壁」です。月間43分なら、障害に気づいて手動で再起動する運用でも達成できる可能性があります。しかし月間4分となると、人間が気づいてから対処する時間はほぼありません。自動フェイルオーバー(障害時に待機系へ自動で切り替わる仕組み)が前提になり、必要なコストと複雑さは桁違いに増えます。
計画停止を含めるかを先に決める
もうひとつ重要なのは、メンテナンスによる計画停止を可用性の計算に含めるかどうかです。含めるなら、深夜のDBメンテナンス1回で月の許容停止時間を使い切ることもあります。事業側と目標値を合意する際は、「何を停止とみなすか」「どの時間帯を対象にするか」を明文化してください。目標値の決め方とエラーバジェットの考え方はSLO・SLI・エラーバジェット入門で詳しく解説しています。
直列と並列で変わる可用性の計算
直列構成:掛け算で下がる
Webシステムは通常、DNS→ロードバランサー→Webサーバー→データベースというように、複数のコンポーネントが直列につながっています。直列では「すべてが動いているときだけ動く」ので、全体の可用性は各要素の可用性の掛け算になります。
# 各要素が99.9%で4段直列の場合
0.999 × 0.999 × 0.999 × 0.999 = 0.9960 → 99.6%(年間約35時間停止)
# 各要素が99.95%でも
0.9995 ^ 4 = 0.9980 → 99.8%
ここが直感に反するところで、部品ひとつひとつが99.9%でも、直列に並べると全体は99.9%に届きません。「うちはAWSを使っているから99.99%」という言い方が成り立たないのは、この掛け算があるからです。
並列構成:同時に壊れる確率だけが残る
同じ役割のサーバーを2台並べ、どちらか片方が生きていればよい構成にすると、停止するのは「両方同時に壊れたとき」だけです。停止確率は掛け算になるので、可用性は大きく上がります。
# 可用性99%のサーバーを2台並列にした場合
停止確率 = (1 - 0.99) × (1 - 0.99) = 0.0001
可用性 = 1 - 0.0001 = 0.9999 → 99.99%
# 3台並列なら
1 - (0.01)^3 = 0.999999 → 99.9999%
ただしこの計算には「2台の故障が独立している」という前提があります。同じラック、同じ電源、同じデータセンターに置いた2台は、停電で同時に落ちます。同じバグを含んだ同じバージョンのアプリは、特定のリクエストで同時にクラッシュします。冗長化の効果を得るには、故障原因を共有しないように配置することが必須です。クラウドで故障の単位を分ける考え方はアベイラビリティゾーンとマルチリージョンで扱います。
単一障害点(SPOF)を洗い出す
SPOFとは「そこが壊れたら全部止まる」場所
単一障害点(SPOF:Single Point of Failure)とは、それが停止するとシステム全体が停止する、代替のない要素のことです。Webサーバーを2台にしても、その前後に1つしかない要素があれば、全体の可用性はそこで頭打ちになります。リクエストの経路をたどりながら、「これが1つしかないものは何か」を書き出してください。
| 層 | よくあるSPOF | 見落としやすい理由 |
|---|---|---|
| DNS | 権威DNSサーバーが1社・1台、レジストラのアカウント | 普段意識しないが、止まると名前解決すらできない |
| ロードバランサー | 自前のNginx/HAProxyが1台 | 「振り分ける側」を冗長化し忘れる |
| アプリ | 1台構成、または2台でもセッションをローカル保存 | 2台あっても片方に固定されて実質1台 |
| データベース | プライマリ1台、レプリカなし | もっとも冗長化が難しく後回しにされがち |
| 共有ストレージ | NFSサーバー1台、アップロード先がローカルディスク | アプリを複数台にした時点で問題化 |
| 外部サービス | 決済API、メール送信、認証基盤 | 自社の管理外なので忘れる |
| ネットワーク | オフィスの回線1本、VPN装置1台 | 社内システムで特に多い |
| 人 | 本番のパスワードや手順を知っているのが1人 | 技術ではなく組織の問題として扱われやすい |
最後の「人」は冗談ではありません。担当者が休暇中に障害が起き、復旧手順もアクセス権も本人しか持っていないために半日止まった、という事例は珍しくないものです。手順書、権限の複数人への付与、連絡網までを可用性設計の一部と考えてください。
トラブル事例:Webサーバー2台なのに全停止
症状:アプリサーバーを2台構成にしてロードバランサーで振り分けていたにもかかわらず、ある朝からサイト全体が503を返して全停止した。2台ともプロセスは生きていた。
原因:2台のアプリが共通で参照していたセッション用のRedisが1台構成で、ディスクフルによりRedisが書き込みを拒否していた。アプリはセッション保存に失敗すると例外を投げて500を返す実装だったため、ロードバランサーのヘルスチェックが両方を異常と判定し、振り分け先がゼロになった。
対処:暫定的にRedisのディスクを整理して復旧。恒久対策として、Redisをレプリカ付き構成に変更し、アプリ側もセッション保存の失敗は致命的エラーにせず警告ログに留めるよう修正。さらに、ヘルスチェックが「依存先の障害で全台が同時に異常判定される」構造にならないよう、チェック内容を見直した。ヘルスチェックの設計はヘルスチェック設計入門を参照してください。
この事例の教訓は、「並列にした部分」の裏で「新たに共有された部分」がSPOFになる、ということです。アプリを複数台にすると、セッション、ファイル、キュー、DBといった共有要素が浮かび上がります。
冗長化のパターン|アクティブ/スタンバイとアクティブ/アクティブ
2つの基本形
冗長化の構成は大きく2つに分かれます。
- アクティブ/スタンバイ:稼働系1台が処理し、待機系は障害時に引き継ぐ。切り替え(フェイルオーバー)の間は短時間停止する。DBのプライマリ/レプリカ構成が典型で、待機系の分だけコストは倍になるが、平常時の性能は変わらない。
- アクティブ/アクティブ:複数台が同時に処理する。1台落ちても残りが処理を続けるので停止時間はほぼゼロ。Webサーバーをロードバランサー配下に並べる構成が典型。ただし、状態(セッション・ファイル)を外に出す必要がある。
Webサーバーやアプリサーバーのように状態を持たない層はアクティブ/アクティブが容易で、効果も大きい部分です。ロードバランサーの仕組みと導入パターンで紹介している構成が、そのまま最初の一歩になります。一方、データベースは書き込みの整合性を保つ必要があるため、アクティブ/スタンバイ(プライマリ+レプリカ、自動フェイルオーバー)が現実的な選択になります。
フェイルオーバーは「試していないなら存在しない」
待機系を用意しても、切り替えを一度も試していなければ、本番障害の当日に初めて動かすことになります。切り替え手順(自動なら発動条件、手動ならコマンド)を文書化し、ステージングで定期的に実行してください。たとえばRDSのマルチAZ構成であれば、次のコマンドでフェイルオーバーを意図的に起こし、アプリが再接続できるか確認できます。
# RDSで手動フェイルオーバーを発生させ、切り替え所要時間とアプリの挙動を確認する
aws rds reboot-db-instance \
--db-instance-identifier prod-db \
--force-failover
# アプリ側では接続エラー後に再接続できるか、コネクションプールが古い接続を捨てるかを確認する
この訓練で「アプリが古いDNSキャッシュを持ち続けて再接続できない」「コネクションプールが切れた接続を使い回してエラーを返し続ける」といった問題が事前に見つかります。
中小規模で現実的な冗長化の優先順位
コストとの釣り合いを数字で考える
冗長化は必ず費用を伴います。判断の軸は「停止1時間あたりの損失 × 減らせる停止時間」と「冗長化の追加費用」の比較です。年間の売上がすべてWeb経由のECサイトと、社内の日報システムでは、同じ1時間の停止でも損失が桁違いに異なります。まず事業側と「1時間止まるといくら損するか」「営業時間外なら?」を合意し、その額に見合う対策だけを選びます。
費用対効果の高い順に取り組む
- バックアップと復旧手順の確立(ほぼ無料):冗長化以前に、壊れても戻せる状態を作る。復旧を実際に試す。
- 人のSPOF解消(ほぼ無料):本番アクセス権と手順書を2人以上で共有し、連絡網を決める。
- 監視とアラート(低コスト):停止に気づく時間を短くするだけで停止時間は大幅に減る。可用性は「壊れない」より「早く戻す」で稼げる。
- マネージドサービスへの移行(中コスト):自前のDB・LB・DNSを、フェイルオーバーが組み込まれたマネージドサービスに置き換える。自分で冗長化するより安く確実なことが多い。
- アプリ層のアクティブ/アクティブ化(中コスト):セッションとファイルを外に出し、2台以上をLB配下に並べる。デプロイ時の無停止化にも効く。
- DBのスタンバイ構成(高コスト):レプリカ+自動フェイルオーバー。DBが最大のSPOFであり、ここまで来て初めて99.9%超が現実になる。仕組みはデータベースレプリケーション入門を参照。
- マルチAZ・マルチリージョン(高コスト):データセンター単位・地域単位の障害への備え。事業影響が非常に大きい場合のみ。
多くの中小規模システムでは、1〜5番までで99.9%に近い水準に到達できます。逆に、1〜3番を飛ばして高価なマルチリージョン構成を組んでも、監視がなく誰も気づかなければ停止時間は減りません。順番を守ることが、もっとも費用対効果の高い可用性向上策です。
まとめ
可用性99.9%は年間8時間46分・月間約44分の停止に相当し、99.99%になると月間4分強で自動フェイルオーバーが前提になります。直列構成では各要素の可用性が掛け算で下がり、並列構成では同時故障の確率だけが残る、という計算を押さえたうえで、DNS・LB・DB・共有ストレージ・外部サービス・人といった単一障害点を経路に沿って洗い出すことが設計の出発点です。
そして冗長化は「高い順」ではなく「費用対効果の高い順」に、バックアップと手順書、人の冗長化、監視、マネージド化、アプリ層の並列化、DBのスタンバイ、と積み上げていくのが中小規模での現実解です。まずは自社システムの経路図を描き、SPOFに印をつけるところから始めてみてください。可用性目標に見合った構成の設計や冗長化の実装にお困りの際は、Harmonic Societyのシステム開発・インフラ支援にご相談ください。
Harmonic Society
この記事の内容、自社の業務でも活かせそうですか?
ローカルLLM・AI・クラウドなどの技術導入を、要件整理からPoC・社内展開まで代表エンジニアが伴走します。オンライン対応・全国OK。まずは30分の無料相談から。売り込みはしません。
関連記事
Related / 9 articles
Notes & Insights
- プログラミング
DDoS攻撃の仕組みと対策入門|レイヤー別の防御とCDN・クラウドの活用
DDoS攻撃をボリューム型・プロトコル型・アプリ層に分けて仕組みを解説し、自前サーバーで防げない理由、CloudflareやAWS Shieldの標準防御、オリジンIPの隠し方、レートリミットとBot対策、攻撃を受けたときの初動、費用が跳ね上がるDenial of Walletへの備えまでわかります。
- プログラミング
WAFとは?仕組み・導入パターン・誤検知対策|Webアプリを攻撃から守る実践ガイド
WAFがファイアウォールやIDSと何が違うのか、シグネチャとマネージドルールの仕組み、Cloudflare WAF・AWS WAF・ModSecurityの比較、フォーム送信がブロックされる誤検知の調査と例外設定、ログ監視、WAFが代替できないことまで実践的に解説します。
- プログラミング
セキュリティヘッダー入門|CSP・HSTS・X-Frame-Optionsの設定と効果を実践解説
CSP・HSTS・X-Frame-Options・X-Content-Type-Optionsなど主要セキュリティヘッダーが防ぐ攻撃と、CSPのReport-Onlyからの段階導入、nonce/hash、HSTS preloadの不可逆リスク、Nginx・Next.js・Astroでの設定例、確認方法を解説します。
- プログラミング
クラウドの通信費(Egress)入門|データ転送量課金の仕組みと転送コストを抑える設計
クラウドの「受信無料・送信有料」の原則、AZ間・リージョン間・インターネット向けの単価差、NATゲートウェイ処理料の罠、CDNで転送量を減らす方法、バックアップやログ転送の見落とし、請求書で転送料を特定する手順を解説。想定外の請求を防げます。
- プログラミング
秘密情報をGitに入れない仕組み|.gitignore・git-secrets・履歴から漏れた鍵の削除
APIキーや.envをGitにコミットしてしまう典型経路と、.gitignore・.env.exampleの運用、pre-commitでのgitleaks検知、GitHub secret scanningの活用、漏れた鍵の無効化と履歴書き換え(git filter-repo)の手順を解説。仕組みで再発を防げます。
- プログラミング
開発・ステージング・本番環境の分離設計|環境差分をなくす構成とアクセス制御
開発・ステージング・本番それぞれの目的と、構成をコードで揃える方法、環境別の設定注入、本番データを使わないテストデータ戦略、ステージングの保護(Basic認証・IP制限・noindex)、コストを抑える運用までを解説。環境差分による本番障害を防げます。
- プログラミング
ngrok・Cloudflare Tunnelでローカルを公開|Webhook開発とデモ環境の作り方
NAT内のローカル環境にStripeやLINEのWebhookを届けるトンネリングの仕組みを解説。ngrok・Cloudflare Tunnel・localtunnelの比較、固定ドメインと認証、リクエスト検査、公開時のセキュリティ、自宅サーバー公開への応用までわかります。
- プログラミング
ローカル開発環境のHTTPS化|mkcert・hostsファイル・自己署名証明書の正しい使い方
ローカル開発をHTTPS前提にすべき理由(Secure Cookie・Service Worker・OAuth)と、mkcertでローカルCAを作りhostsで独自ドメインを割り当ててVite・Next.js・Dockerで使う手順を解説。証明書警告を無視する癖の危険も理解できます。
- プログラミング
localhost・0.0.0.0・127.0.0.1の違い|ポートとUnixソケットを理解して「つながらない」を解決
localhost・127.0.0.1・0.0.0.0の意味の違い、Dockerで外から接続できない原因、host.docker.internal、ポート競合の調べ方、Unixソケットの利点と権限、1024未満ポートの制約を解説。「つながらない」を仕組みから解決できます。
Harmonic Society
「読んで終わり」にせず、自社の業務で試してみませんか?
AI・ローカルLLM・クラウドの導入を、要件整理からPoC・社内展開まで代表エンジニアが伴走します。オンライン対応・全国OK・売り込みなし。
無料・30分・オンラインOK|1営業日以内に返信します