SYSTEM ARCHITECTURE / AVAILABILITY / FAILOVER
Webサーバーの冗長化とは? セッション共有・フェールオーバー・DBトランザクションを図解で理解する
公開日:2026-10-14
Next.jsとSupabaseを使って予約アプリを作ったとします。予約確定の直前にWebサーバーが止まったら、別のサーバーへ切り替えるだけで元どおりになるでしょうか。答えは「どの状態をどこに保存しているか」によって変わります。今回は、一つの予約操作を追いながら、可用性とデータの整合性を丁寧に整理します。
身近な予約アプリ → Webの構成 → セッションとは → 冗長化 → フェールオーバー → セッション共有 → DBトランザクション → Supabaseでの設計 → 可用性指標 → 操作ラボ
01|予約ボタンを押した瞬間にサーバーが止まったら
例えば、予約サイトで日時と人数を選び、「予約する」を押す場面を考えてください。画面はNext.js、認証はSupabase Auth、予約データはPostgresという構成が一例です。押した直後に処理担当のサーバーが停止すると、通信が失敗したり、結果が分からなくなったりします。
ブラウザ
予約日と人数を入力
Webの処理
ユーザーと在庫を確認
データベース
予約レコードを確定
完了画面
予約番号を表示
Webサーバーが停止しても、すでにDBで確定した予約まで自動的に取り消されるわけではありません。どの時点で失敗したかが重要です。
02|まずWebサーバーとデータベースの役割を分けます
Webアプリは一つの箱に見えますが、画面を提供する部分、リクエストを処理する部分、状態を保存する部分に分かれています。これらを分けておくと、障害時に何が残り、何が失われるかを考えやすくなります。
| 技術・状態 | 何を守るか | 障害時のポイント |
|---|---|---|
| ブラウザ | 入力フォームやCookieを持ちます | 再読み込みで消える入力がある一方、Cookieは残る場合があります。 |
| アプリケーションサーバー | 処理を実行し、一時的な状態を保持します | プロセス内メモリにしかない情報は停止すると失われます。 |
| セッションストア | 複数リクエスト間の利用者状態を保持します | サーバー外へ共有すれば別インスタンスから参照できます。 |
| データベース | 予約などの確定情報を永続化します | DBトランザクションの境界が確定・取消しを決めます。 |
03|「ログイン中」はどこに保存されていますか
HTTP(Hypertext Transfer Protocol)は、基本的に個々のリクエストを独立して扱います。ユーザーがログインしているか、買い物カゴに何を入れたかを扱うために、Cookieやトークン、サーバー側セッションなどの仕組みを使います。
Cookie/トークン
ユーザーを識別・認証
セッション状態
入力途中の手順やカート
DBレコード
確定した予約・決済情報
JWTのような署名付きトークンで状態を検証できる方式もあります。すべての構成で共有セッションストアが必要なわけではありません。
サーバーAだけのメモリに「予約の第2画面まで進んだ」という情報を持っていると、次のリクエストがサーバーBへ届いても、Bはその情報を知りません。これがセッションを共有しない構成の問題です。
04|可用性と信頼性は何を意味しますか
可用性(Availability)は必要なときにサービスを使える度合いです。信頼性(Reliability)は一定条件のもとで正しく動作し続ける性質を指します。Webサービスでは、故障しても別の装置へ切り替えられるように設計することが重要です。
| 技術・状態 | 何を守るか | 障害時のポイント |
|---|---|---|
| 冗長化(Redundancy) | 同じ機能を担う複数の資源を用意します | 1台停止しても別の系が対応できます。 |
| フェールオーバー(Failover) | 障害を検知し、予備系へ切り替えます | 切替えには検知・再接続の時間がかかる場合があります。 |
| フェールバック(Failback) | 復旧した元の系へ戻す処理です | 戻し方も運用設計の対象です。 |
| 単一障害点(SPOF) | ここが壊れると全体が止まる箇所です | ロードバランサーやDB自身にも注意が必要です。 |
05|コールド・ウォーム・ホットスタンバイの違い
「予備がある」だけでは切替え速度を判断できません。コールドスタンバイは予備機の起動や初期化が必要になりやすく、ウォームスタンバイは一部準備済み、ホットスタンバイはすぐ引き継げる状態を維持する設計です。ただし用語の厳密な運用は製品ごとに異なります。
時間の長さを定量化した図ではありません。ホット構成でも無停止が必ず保証されるわけではありません。
| 技術・状態 | 何を守るか | 障害時のポイント |
|---|---|---|
| コールドスタンバイ | 予備を起動・設定してからサービスを引き継ぎます | 障害後に待ち時間が発生します。 |
| ウォームスタンバイ | 一部を起動・同期して待機します | ホットより準備が少なく切替え時間が長い場合があります。 |
| ホットスタンバイ | すぐに処理を受けられるよう準備します | 同期状態や通信切替えにより瞬断する場合があります。 |
| アクティブ・アクティブ | 複数系が平常時から要求を処理します | 状態共有と負荷分散が重要です。 |
06|ロードバランサーは何をするのですか
LB(Load Balancer、ロードバランサー)は、正常なサーバーへリクエストを振り分けます。ヘルスチェックで故障を検出し、送信先から外す仕組みを組み合わせます。ただし、すでに実行中の処理をそのまま移動させるわけではありません。
利用者
予約画面を操作
LB
Aの障害を検知
WebサーバーB
新しい要求を処理
Aで実行中だった要求は失敗した可能性があります。新しい要求をBで受け付けられることと、途中処理の継続は別問題です。
07|セッションを共有すると何が変わりますか
AとBの両方が共通のセッションストアへアクセスできれば、「入力を何段階進めたか」「一時的な選択内容」などをBが参照できます。セッション共有は、利用者が別サーバーへ移った後の操作の継続を助けます。
WebサーバーA
途中状態を保存
共有ストア
session_id → 選択内容
WebサーバーB
同じ状態を読み出す
08|セッション維持とDBトランザクションは別物です
DBトランザクション(Transaction)は、予約レコードの書込みなど複数のDB操作を、一つの整合した処理単位にまとめます。原子性(Atomicity)により、COMMIT前に異常終了した場合は変更がロールバックされるのが基本です。
BEGIN
処理単位を開始
在庫を確認
空き枠をロック等で保護
予約を登録
必要なDB更新
COMMIT
まとめて確定
| 技術・状態 | 何を守るか | 障害時のポイント |
|---|---|---|
| ログインセッション | 利用者が誰か、操作の文脈 | サーバー外で保持すれば別のWebサーバーから利用できます。 |
| DBトランザクション | DB更新を整合的に確定する単位 | 途中で接続が失われれば、通常はロールバックされます。 |
| HTTPリクエスト | 利用者が送った1回の通信 | 接続切断後の再送と重複処理に注意が必要です。 |
09|Supabaseを使った予約アプリならどう設計しますか
Supabase Authでは認証状態を扱い、Postgresに予約データを保存できます。画面表示を担当するWebサーバーが入れ替わっても予約情報を参照できるよう、確定情報を特定サーバーのメモリだけに置かないのが大切です。
// ブラウザ: 認証済みのユーザーとして予約要求を送信します
POST /api/reservations
{
"timeSlot": "2026-10-20T18:00:00+09:00",
"requestId": "reservation-attempt-001"
}
// Web API側の責務(設計イメージ)
// 1. Supabase Authでユーザーを検証します。
// 2. DBで requestId の重複を確認・制約で保護します。
// 3. 在庫確認と予約登録をDBの単一トランザクションで扱います。
// 4. 既に成功済みの requestId なら同じ結果を返します。複数のDB操作を一つのトランザクションにまとめたい場合は、Postgresの関数などDB側で処理を完結させる設計が考えられます。上記は設計方針を示した擬似コードで、そのまま動くSupabase API実装ではありません。
10|二重予約を防ぐには冪等性が重要です
処理完了後、応答だけが届かないことがあります。利用者がもう一度「予約」を押すと、同じ処理が二重に実行されるおそれがあります。そこで冪等性(Idempotency、べきとうせい)を使います。同じリクエストIDの再送で結果が二重に増えないようにする設計です。
予約がDBで確定
1件作成されました
HTTP応答が途切れる
画面では結果が不明
同じIDで再送
重複登録せず既存の結果を返します
実装では一意制約、原子的なINSERT、適切なトランザクション境界、要求IDの保存などを組み合わせます。「同じデータのSELECT結果になる」だけでは二重登録の防止にはなりません。
11|フェールオーバーとフェールソフト・フォールトトレランス
関連する用語も整理しておきます。フェールオーバーは系の切替えです。フォールトトレランス(Fault Tolerance、耐障害性)は障害下でも処理を続けられる性質を表します。フェールソフト(Fail-soft)は機能や性能を落としてもサービスの一部を提供し続ける考え方です。
| 技術・状態 | 何を守るか | 障害時のポイント |
|---|---|---|
| フェールオーバー | 障害時に別の系へ切り替えます | 切替えの瞬間に通信が失敗する場合があります。 |
| フェールソフト | 機能を縮小しても稼働を続けます | 予約は止めても一覧閲覧だけ維持する例があります。 |
| フェールセーフ | 故障時に安全側へ制御します | 決済の確定を保留するなど、不整合を避ける設計です。 |
| フォールトトレランス | 障害の発生を見越した継続能力です | 多重化・検出・復旧の仕組みを組み合わせます。 |
12|可用性・MTBF・MTTR・RTO・RPOを区別します
可用性を数値で考える場合は、稼働時間と修復時間が重要です。MTBF(Mean Time Between Failures、平均故障間隔)、MTTR(Mean Time To Repair、平均修復時間)を使う単純なモデルでは、稼働率 A は次の式で表せます。
A = MTBF / (MTBF + MTTR)
例:MTBF = 990時間、MTTR = 10時間
A = 990 / 1000 = 0.99(99%)RTO(Recovery Time Objective、目標復旧時間)は停止から復旧するまでの目標、RPO(Recovery Point Objective、目標復旧時点)は障害前のどこまでデータを復元できればよいかの目標です。可用性が高いことと、失われるデータ量が少ないことは別々に考えます。
| 技術・状態 | 何を守るか | 障害時のポイント |
|---|---|---|
| MTBF | 平均故障間隔 | 長いほど障害間隔が長い傾向です。 |
| MTTR | 平均修復時間 | 短いほど復旧が速い傾向です。 |
| RTO | 復旧に許される目標時間 | 例:15分以内に業務を再開します。 |
| RPO | 許容できるデータ損失の目標時点 | 例:直前5分までのデータを復元します。 |
13|アプリの冗長化だけでは不十分な理由
Webサーバーを2台にしても、両方が同じ単一DBへ依存し、そのDBが停止すれば予約処理は止まります。LB、セッションストア、DB、ネットワーク、認証基盤など、複数の依存先を考えなければなりません。
ロードバランサー
入口が止まると到達できません
Webサーバー群
複数台でも共有状態が必要です
データベース
永続データと整合性を守ります
14|ラボ:サーバーAを停止して違いを確かめましょう
次のシミュレーターでは「コールドスタンバイ」「クラスタ・セッション非共有」「クラスタ・セッション共有」を切り替えられます。ログイン・入力・予約要求・障害を順番に試し、状態がどこに残るのか観察してください。DB側はWebサーバーと独立した学習モデルです。
INTERACTIVE LAB
予約サーバーの障害と状態の引継ぎ
ステップを進めると、サーバー停止・セッション共有・DBの確定状態がそれぞれどう変化するか確認できます。データベースと共有ストアが正常な単純化モデルです。
AとBが共通のセッションストアを参照します。Aが止まっても入力途中の状態を読み直せます。
サーバーA
稼働中
サーバーB
待機中
入力した予約日時
未入力
共有ストア:保存なし
データベースの予約
確定 0 件
処理中:なし
二重予約防止の動きを確認します
ここではIDの重複をDB側で原子的に防止できるものと仮定します。実際には一意制約などが必要です。
イベントログ
- 初期状態です。サーバーAで入力を始め、次に障害を発生させてください。
現在のステップ:0。障害検知やDBの整合性を学ぶためのモデルであり、実サービスの可用性やSupabaseの内部動作をシミュレートするものではありません。
15|まとめ:守りたい状態を分けて設計します
複数サーバーを用意することは、可用性向上の出発点です。しかし、セッションがAのメモリにしかなければ、Bへ切り替えたあとに操作状態を失います。さらに、共有セッションがあってもDBトランザクションの自動継続まで保証されるわけではありません。
Webの構成、利用者状態、DBでの確定処理、再送時の冪等性を別々に設計することが、実際のシステムを堅牢にする近道です。