高可用性設計の基本——SPOF排除とフェイルオーバーで「止まらないサービス」を作る

単一障害点(SPOF)を排除し、障害が起きても自動で切り替わる仕組みを作るための高可用性設計の考え方。Active-Standby・Active-Activeの使い分けと実務の落とし穴。

「サービスを止めない」は、運用に入ってから初めてその重さを実感する。

開発中は「落ちたら直せばいい」と思いがちだが、本番運用が始まると1分のダウンタイムがユーザーの離脱や信頼の損失に直結する。『24時間365日 サーバ/インフラを支える技術』では、高可用性設計の考え方が体系的に整理されており、インフラを本格的に学ぶきっかけになった。

SPOFとは何か

**SPOF(Single Point of Failure:単一障害点)**とは、そこが止まるとシステム全体が止まるコンポーネントのことだ。

高可用性設計の出発点は「SPOFを見つけて排除する」ことだ。

# SPOFがある構成(危険)
クライアント → Webサーバ(1台) → DB(1台)

# SPOFを排除した構成
クライアント → ロードバランサ → Webサーバ × 2台 → DB(マスター/スレーブ)

Webサーバが1台しかない場合、そのサーバが落ちた瞬間にサービス全体が止まる。複数台構成にすることで、1台が落ちても残りが処理を引き継ぐ。

Active-Standby vs Active-Active

冗長化の方式には大きく2種類ある。

Active-Standby(待機冗長)

メイン機が動いている間はサブ機は待機。メイン機が落ちたらサブ機が引き継ぐ。

項目内容
コストサブ機は待機中コストがかかる
切り替え速度フェイルオーバーに数秒〜数十秒かかる
向いているものDB(マスター)・ステートフルなコンポーネント

Active-Active(負荷分散冗長)

複数台が同時に稼働し、ロードバランサが負荷を分散する。1台が落ちても残りが処理を継続。

項目内容
コスト全台が稼働するため効率的
切り替え速度ほぼ瞬時(ヘルスチェックで除外)
向いているものWebサーバ・APIサーバ・ステートレスなもの

ステートレスにできるかどうかがActive-Activeにできる条件だ。セッション情報や状態をサーバ内に持っていると、どのサーバに振られるかによって挙動が変わってしまう。

フェイルオーバーの仕組み

障害時に自動で切り替わる仕組みがフェイルオーバーだ。

ヘルスチェック

ロードバランサは定期的に各サーバの死活確認(ヘルスチェック)を行う。応答がなければそのサーバへのルーティングを止め、正常なサーバにのみ振り分ける。

# ロードバランサのヘルスチェック設定(概念)
チェック間隔: 30秒
タイムアウト: 5秒
失敗しきい値: 3回連続で失敗したらアウト

ヘルスチェックの間隔と失敗しきい値の設定が重要で、厳しすぎると一時的な遅延でも切り離されて過剰に縮退し、緩すぎると障害のサーバへのルーティングが続く。

DBのフェイルオーバー

DBのフェイルオーバーはWebサーバより複雑だ。マスター昇格(スレーブをマスターに昇格させる)のタイミングで、未同期のデータが失われるリスクがある。

AWS RDSのMulti-AZ構成では、フェイルオーバーが自動化されており、通常1〜2分程度で切り替わる。

# RDS Multi-AZ の構成
マスター(AZ-a) ←同期レプリケーション→ スタンバイ(AZ-b)
マスター障害時: スタンバイが自動でマスターに昇格
エンドポイント: 変わらない(アプリ側の変更不要)

セッション管理の落とし穴

Active-Active構成でWebサーバを複数台にしたとき、セッション情報の扱いに注意が必要だ。

スティッキーセッション(危険):同じユーザーのリクエストを常に同じサーバに振り続ける方式。サーバが落ちたときにセッションが消える。根本解決ではない。

セッションの外部化(正しい対応):セッション情報をRedisなどの外部ストアに保存する。どのサーバに振られても同じセッションを参照できる。

// Expressでのセッション外部化例
import session from 'express-session';
import RedisStore from 'connect-redis';

app.use(session({
  store: new RedisStore({ client: redisClient }),
  secret: process.env.SESSION_SECRET!,
  resave: false,
  saveUninitialized: false,
}));

マルチAZ構成でSPOFを排除する

AWSでは、複数のAvailability Zone(データセンター)にリソースを分散させることで、データセンター単位の障害に耐えられる。

# シングルAZ構成(AZ障害でサービス停止)
クライアント → ALB → EC2(AZ-a)→ RDS(AZ-a)

# マルチAZ構成(AZ障害でも継続)
クライアント → ALB → EC2(AZ-a)
                    → EC2(AZ-b)
                 → RDS マスター(AZ-a)+ スタンバイ(AZ-b)

コストは増えるが、本番サービスでマルチAZを避ける理由はほとんどない。AZ障害は年に何度か実際に起きており、対策していないシステムは必ず影響を受ける。

治験システムで「止められない」要件に向き合ったこと

治験(臨床試験)のシステムには「止められない」という圧力が一般的なWebサービスとは比較にならないほど強くかかる。

被験者への投薬スケジュールや有害事象の記録が止まることは、患者の安全に関わる問題になりうる。モニタリング訪問の直前にシステムが落ちれば、製薬会社との信頼関係に直結する。「1分のダウンタイムが信頼の損失につながる」という話は他の業種でも聞くが、医療系では文字どおりそれが現実だ。

最初に本番システムを触ったとき、構成はWebサーバ1台・DB1台のシンプルなもので、明らかにSPOFだらけだった。前任者は「今まで落ちたことない」と言ったが、落ちていないのは運が良かっただけで、それはリスクが存在しないこととは違う。

改善のためにまず取り組んだのがDBのMulti-AZ化だった。RDS Multi-AZに移行してフェイルオーバーを自動化したとき、製薬会社の担当者から「DR(ディザスタリカバリ)対策が確認できた」という言葉をもらった。技術的な設計が、外部監査の評価に直結した経験だ。

もうひとつ痛感したのはセッション管理の問題だ。Webサーバを複数台に増やしたとき、スティッキーセッションで一時しのぎしていた設計が悲鳴を上げた。1台がメンテナンスに入るたびにユーザーが強制ログアウトされ、クレームが来た。本書で「セッションの外部化」を学んでRedisに移行したことで、ノードを自由に増減できるようになった。

まとめ:高可用性設計のチェックリスト

設計時に確認すべき項目を整理する。

  • WebサーバはActive-Active構成で複数台か
  • DBはマスター/スレーブ構成またはManaged DBのMulti-AZか
  • [ ]セッションは外部ストアに保存しているか(スティッキーセッション依存ではないか)
  • [ ]ロードバランサ自体がSPOFになっていないか(AWSのALB/NLBは内部的に冗長化済み)
  • [ ]複数のAZにリソースが分散されているか
  • [ ]ヘルスチェックの間隔・しきい値は適切か

高可用性設計は「障害が起きないようにする」のではなく「障害が起きても止まらないようにする」という発想の転換が重要だ。