【実務・中級編】 ネットワークパーティション処理 – Cloud Spanner

ネットワーク分断の嵐を生き抜く:Cloud SpannerのPaxos合意と無停止アーキテクチャの深層

こんにちは。チーフアーキテクトの私だ。
今日のコードレビュー、あるいは基本設計レビューで、こんな質問を受けたことはないか?

> 「もしリージョン間でネットワーク分断(スプリットブレイン)が起きたら、Spannerのデータはどうなるんですか? 本当に止まらないんですか?」

この質問に「Googleのマネージドだから安心です」と答えたとしたら、今すぐその設計書を閉じたまえ。君は巨大な分散システムの深淵の、まだ入り口にすら立っていない。

Cloud Spannerは、単なる「リレーショナル機能を持ったNoSQL」ではない。真に恐るべきは、グローバル規模での強整合性(External Consistency)と、ネットワーク分断に対する圧倒的な耐性を、PaxosグループとTrueTimeという狂気的なまでの物理時計の同期によって両立させている点にある。

今日は、ネットワークパーティション(分断)という分布式システムの悪夢の中で、Spannerの内部(Paxos)がどのように鼓動し、一貫性を保ち続けているのか。その極限の知見を、実務の設計に直結するレベルで解き明かしていこう。

—

1. 前提知識の破壊:Spannerの最小単位は「インスタンス」ではない

多くのエンジニアは、Spannerのサイジングや可用性を語るときに「リージョン」や「インスタンス」単位で思考する。だが、アーキテクチャの根底において、Spannerの運命を握るのは Paxosグループ(Replicaの集合) だ。

Spannerのデータは、連続したキー範囲ごとに「スプリット」され、複数のトランスポート(Paxos Group)に分割されて管理されている。
例えば、日本(asia-northeast1)と台湾(asia-east1)にまたがるマルチリージョン構成(例: `nam-eur-asia` などのカスタムマルチリージョン)を組んだ場合、各データシャードは通常 5つのレプリカ(Read-Write Replica) を異なるゾーン/リージョンに分散して配置する。

この5つのレプリカの間で、常に何が行われているか? それが Paxosアルゴリズムによるステートマシンレプリケーション だ。

—

2. ネットワーク分断発生:Paxosグループの内部で何が起きるか?

では、ここに悪夢を想定しよう。
東京(zone-a, zone-b)と大阪(zone-c)、そして海外の拠点をつなぐ海底ケーブルやバックボーンネットワークで障害が発生し、完全なネットワーク分断(Network Partition) が起きたとする。

  • マイノリティ側(少数派): 2つのレプリカが孤立
  • マジョリティ側(多数派): 3つのレプリカが疎通を維持

この瞬間、分散データベースの歴史において最も厄介な問題である 「スプリットブレイン(Split-Brain)」 の危機が訪れる。もし双方が独立して書き込みを受け付ければ、データは完全に破壊され、二度と修復不可能なパラレルワールドが誕生する。

だが、Spannerは崩壊しない。なぜか? Paxosの数学的絶対性 がそれを許さないからだ。

Paxosの過半数(Quorum)原則による自己防衛

Paxos合意において、新しい状態(トランザクションログ)をコミットするには、過半数(Quorum)の合意が絶対条件となる。

  • 5つのレプリカが存在する場合、過半数は 3 である。

ネットワーク分断によって以下のような状況になったとしよう。

[ マジョリティ側 (3レプリカ) ] <--- 正常通信 ---> [ リーダー(Leader)存在 ]
========================= 巨大な壁 (分断) =========================
[ マイノリティ側 (2レプリカ) ] <--- 孤立状態 ---> [ リーダー選出不可能 ]

1. マジョリティ側(3レプリカ)の挙動:

  • 全体の過半数を占めているため、リーダーは自身の生存(Heartbeat)を他の2つと確認し続けられる。
  • クライアントからの読み書きリクエストは何事もなかったかのように処理され続ける。可用性と一貫性は完全に維持される。

2. マイノリティ側(2レプリカ)の挙動:

  • 過半数(3)の票を集めることが物理的に不可能になる。
  • 新しいリーダーを選出できず、既存のリーダーもマジョリティとのハートbeatが途絶えるため、即座に書き込みの受付を停止(Fail-stop) する。
  • マイノリティ側のレプリカに接続しようとしたクライアントのリクエストは、タイムアウトまたはエラー(Unavailable)を返す。

ここで重要なのは、「システム全体としては可用性を維持しながら(マジョリティが生きているため)、不整合の発生を完全に防いでいる」という点だ。CP(CAP定理)の文脈において、Spannerはネットワーク分断時には「一貫性(Consistency)」と「可用性(Availability:ただしマジョリティ側のみ)」の絶妙なトレードオフを、Paxosの動的クォーラムによって自動制御している。

—

3. 実務へのインプリケーション:設計レビューで何を考慮すべきか?

このアーキテクチャを理解していると、実務でのデータベース設計やインフラ構成のレビュー時に、見るべきポイントが劇的に変わる。以下の「3つのアンチパターン」を避けるための設計指針を授けよう。

アンチパターン A: 「2リージョン(2データセンター)構成」で高可用性を狙う

予算の都合で「東京と大阪の2箇所にレプリカを置こう」と提案するジュニアエンジニアがいたら、即座に止めろ。

理由:
レプリカ数が「2」の場合、過半数は「2」になる。つまり、東京と大阪を繋ぐネットワークが一度でも切断された瞬間、双方のリージョンが過半数を割るため、システム全体の書き込みが完全に停止する。
マルチリージョンで高可用性(HA)を担保したいなら、レプリカ数は必ず奇数(最低3、推奨は5)にし、障害ドメイン(Failure Domain)が綺麗に分散する配置にしなければならない。

アンチパターン B: ネットワーク分断時のアプリケーション側のリトライ設計の欠如

マジョリティ側にルーティングされているクライアントは動き続けるが、マイノリティ側に接続していた一部のクライアントは一時的にエラーを食らう。ここでアプリケーションが「指数バックオフ(Exponential Backoff)とジッター(Jitter)」を用いた適切なリトライを実装していないと、ネットワークが復旧した瞬間にリクエストの津波(Thundering Herd現象)が発生し、データベースを二次災害に追い込むことになる。

推奨されるクライアント設定の例(Java / Spanner Client)

// スパナーの接続設定におけるリトライとタイムアウトのチューニング例
SpannerOptions options = SpannerOptions.newBuilder()
.setProjectId(“my-production-project”)
.setRetrySettings(
RetrySettings.newBuilder()
// ネットワーク分断やリーダー再選出の瞬間のためにリトライ回数を十分に確保
.setMaxAttempts(10)
.setInitialRetryDelay(Duration.ofMillis(100))
.setMaxRetryDelay(Duration.ofSeconds(5))
.setRetryDelayMultiplier(2.0)
.build()
)
.build();

プロからの助言: クライアントライブラリは、リーダーの移動や一時的な分断に伴うエラー(`ABORTED` や `UNAVAILABLE`)を自動的にハンドリングしてリトライするよう設計されているが、アプリケーション側でもコネクションプールの枯渇やタイムアウト値を安易に短く設定しないことだ。

—

4. パーティション治癒(Healing):スプリットブレインの「その後」

ネットワーク分断が解消されたとき、システムはどのように収束するのか?
ここにもPaxosの美しさが宿っている。

1. リーダーの再調停:
分断が治癒すると、マイノリティ側にいたレプリカたちは、マジョリティ側で進んでいたPaxosのログ(インデックス)の方が先を進んでいることに気づく。
2. キャッチアップ(Log Compaction / Catch-up):
マイノリティ側は自身の状態を捨て、マジョリティ側から最新のPaxosログを取得して高速に追従(Catch-up)する。
3. TrueTimeによる無矛盾性の担保:
仮に分断の最中に、マイノリティ側が古いデータを保持したまま何らかの奇跡で読取リクエストを受け付けたとしても(SpannerのRead-Onlyスプレッドの場合)、TrueTimeの不確実性ウィンドウ($\epsilon$)の仕組みにより、因果関係の逆転や不整合なデータが外部に見えることは数学的に排除される。

—

結びにかえて

Cloud Spannerのネットワーク分断に対する挙動は、魔法ではない。それは、厳密な分散合意アルゴリズム(Paxos)と、物理時間を束ねるインフラ(TrueTime)の血の滲むようなエンジニアリングの結晶である。

「なぜこのレプリカ配置なのか?」
「ネットワークが分断されたとき、どのノードがクォーラムを握るのか?」

この問いを常に頭に置きながら設計に向き合えば、君が構築するシステムは、いかなるインフラの嵐が吹こうとも、決して揺らぐことはないだろう。

さあ、コードを書こう。そして、設計の限界をさらに押し上げるんだ。

コメント

タイトルとURLをコピーしました