【実務・中級編】 Paxosコンセンサスアルゴリズム – Cloud Spanner

【Cloud Spannerの核心】Paxosコンセンサスアルゴリズムと強整合性の裏側:シニアアーキテクチャ設計論

こんにちは。テクニカルリードの私だ。
今日のコードレビュー、あるいは昨日のアーキテクチャ設計ミーティングで、こんな質問を受けたことはないだろうか?

  • 「Cloud Spannerって、グローバルにデータを分散させながら、どうやって一瞬で整合性を保っているの?」
  • 「RDB並みの強整合性(Serializable)を持ちながら、なぜ無限にスケールするの?」
  • 「マルチリージョン構成にしたとき、書き込みのレイテンシと可用性のトレードオフはどう評価すべき?」

これらに淀みなく答え、さらに「だから我々のシステムではこう設計する」とロジカルに提示できるかどうかが、クラウドネイティブ時代のシニアエンジニアの分水嶺だ。

今回は、Cloud Spannerの心臓部であり、すべての魔法の源泉である 「Paxosコンセンサスアルゴリズム」 に真っ向から焦点を当てる。教科書的なアルゴリズムの解説は他の記事に譲る。ここでは、「実務のシステム設計にどう影響するか」「パフォーマンスを極限まで引き出すためにどう振る舞うべきか」という、実戦知見だけに絞ってシャープに伝授しよう。

—

1. なぜSpannerにPaxosが必要なのか?(前提の破壊)

多くのエンジニアが犯す最初の勘違いは、こうだ。

  • “Cloud SpannerはGoogleのすごいRDBだから、マスターノードがあって、そこに書きに行っているんでしょ?”

完全な誤りだ。 Cloud Spannerには、伝統的なリレーショナルデータベースが持つ「単一のマスターノード」という概念が存在しない。単一障害点(SPOF)を作ることは、Googleの哲学に反するからだ。

その代わり、Spannerはデータを小さな断片(スプリット / Split)に分割し、それぞれを複数のサーバー(Paxosグループ)に分散配置している。

ここで発生する物理的な課題が、CAP定理の壁である。
物理的な距離(例えば、東京とオレゴン)がある以上、ネットワークの遅延は光速を超えることはできない。その環境で、複数の拠点が「今、このデータが正しい」と合意(Consensus)を形成し、トランザクションを完結させる必要がある。

そこで採用されているのが、Paxosアルゴリズムだ。

—

2. SpannerのPaxos実装:実務で知るべき3つの事実

SpannerのPaxosは、単に論文の理論を実装したものではない。グローバルスケールでミリ秒単位のレイテンシを実現するための「極限の最適化」が施されている。

事実①:リーダーレスではなく「リーダー駆動型Paxos(Multi-Paxos)」

Spannerの各スプリットのPaxosグループには、Paxosリーダー(正確にはリーダーレプリカ)が選出される。
書き込み(Write)および読み取り(Read/Writeトランザクション)のオーケストレーションは、必ずこのリーダーを経由して行われる。

  • 設計上の意味:

書き込みリクエストは、リーダーに対して行われる。もしあなたが東京リージョンから書き込みを行い、そのスプリットのリーダーが東京にあるなら、Paxosの過半数(Quorum)の合意形成は高速に終わる。しかし、リーダーがオレゴンにある場合、往復の物理的レイテンシがそのままトランザクションのレイテンシに乗る。
👉 設計原則: 「データの局所性(Locality)」を意識し、頻繁に更新するデータのリーダーがどこに位置するかをアーキテクチャの初期段階でコントロールせよ。

事実②:ハードウェア障害を秒単位で乗り越える「自動フェイルオーバー」

Paxosの最大の美しさは、過半数($N/2 + 1$)が生存していれば、少数派のノードが死のうが、ネットワークが分断されようが、システム全体としての可用性と整合性が維持される点だ。

Spannerの裏側では、ハードウェアの故障、ラックの電源喪失、果てにはデータセンター全体の火災などが日常茶飯事として起きている。しかし、Paxosグループが自動的に新しいリーダーを選出し、ミリ秒単位で復旧するため、アプリケーション層からは「一瞬レイテンシが揺らいだ」程度にしか見えない。

  • 設計上の意味:

アプリケーション側で無駄なリトライ機構やサーキットブレーカーを過剰に作り込む必要はない。Spannerのインフラストラクチャ層がそれをハンドリングする。信頼するのはアプリの独自実装ではなく、Paxosの数学的証明だ。

事実③:TrueTime APIとの共生

Spannerの強整合性(External Consistency)の秘密は、Paxos単体にあるのではない。Paxosが「順番(順序)」を合意し、Googleが誇る原子時計とGPSレシーバーによる時刻同期API 「TrueTime」 が「絶対時間(タイムスタンプの確度:Uncertainty)」を与える。

この2つが組み合わさることで、「ロックなしの読み取り(Read-Only Transaction)」や「分散トランザクションの直列化」がグローバル規模で破綻なく成立する。

—

3. コードレビューで指摘すべき「Paxosを殺すアンチパターン」

テクニカルリードとして、私はチームメンバーが書くクエリやスキーマ設計をレビューする際、Paxosの挙動を脳内でシミュレーションする。以下のアンチパターンを見つけたら、即座に差し戻しを要求してほしい。

アンチパターン A: 「ホットスポット(Hotspot)」の生成

あるテーブルのプライマリキーの先頭に、インクリメンタルなIDや、現在時刻のタイムスタンプ(`2023-10-27-00:00:00…`)をそのまま置いていないか?

— 【悪夢のスキーマ例】
CREATE TABLE AccessLogs (
LogTimestamp TIMESTAMP NOT NULL, — 先頭にタイムスタンプ!
UserId STRING(64) NOT NULL,
Action STRING(MAX),
) PRIMARY KEY (LogTimestamp, UserId);

何が起きるか?

Spannerはプライマリキーの順序に基づいてデータをスプリットに分割する。先頭にタイムスタンプを置くと、現在時刻の書き込みがすべて「単一のスプリット(単一のPaxosグループ)」に集中(ホットスポット化)する。
結果として、そのグループのリーダーノードのCPUが完全に飽和し、Paxosの合意形成が遅延し、システム全体のスループットが劇的に低下する。Paxosの分散のメリットが完全に殺される。

正しい設計(スプリットの分散)

プライマリキーの先頭にハッシュ値のプレフィックスを付与するか、UUIDv4(あるいは逆ビット化したID)を使用し、書き込みを空間的に均等に分散(シャード)させなければならない。

— 【洗練されたスキーマ例】
CREATE TABLE AccessLogs (
ShardId INT64 NOT NULL, — 0〜15程度でハッシュ分散させるプレフィックス
UserId STRING(64) NOT NULL,
LogTimestamp TIMESTAMP NOT NULL,
Action STRING(MAX),
) PRIMARY KEY (ShardId, UserId, LogTimestamp);

※シャードIDを設けることで、書き込みが異なるPaxosグループへ並列に分散し、Paxosの真価が発揮される。

—

4. パフォーマンス上の注意点:マルチリージョン構成とPaxosの代償

「可用性を高めるために、マルチリージョン(例: `nam-eur-asia` や `us-east1` と `us-west1` のマルチリージョン)にしよう」
これはよくある要件だが、Paxosの仕組みを理解している者なら、ここで一歩踏み止まってコストとレイテンシを計算するはずだ。

書き込みレイテンシの物理的制約

マルチリージョン構成(リーダーが遠隔地にある場合や、クォーラムの過半数が物理的に離れたリージョンに配置されている場合)、書き込みは物理的な往復時間(RTT)の支配下から逃れられない。

  • 東京と大阪のRTT:約10ms
  • 東京とオレゴンのRTT:約100ms以上

Read/Writeトランザクションをコミットするためには、Paxosグループの過半数からの「同意(Acknowledgement)」を得る必要がある。つまり、遠く離れたリージョン間のネットワークを往復する時間が、そのまま書き込みのレイテンシに加算される。

> リードの最適化:
> 一方で、読み取りのみ(Read-Only Transaction)や、過去のタイムスタンプを指定した読み取り(Stale Read)であれば、ローカルレプリカ(Read-Only Replica)からPaxosの合意形成をバイパスしてミリ秒単位でデータを取得できる。

テクニカルリードとしての判断基準:

  • レイテンシがシビアなB2Cトランザクション系: シングルリージョン(プラス、非同期レプリカによるバックアップ)を検討する。
  • 絶対に止まらないミッションクリティカルなFintech・グローバルSaaS: マルチリージョンのPaxosクォーラムのコスト(レイテンシと費用)を受け入れ、その上でアプリケーション側のバッチ処理や非同期化を徹底する。

—

5. まとめ:Spannerを使いこなすということ

Cloud Spannerの底力は、開発者に「複雑な分散システムの苦悩」を意識させないことにある。しかし、「意識しなくてよい」ことと「知らなくてよい」ことは全く別だ。

底流で動いているPaxosコンセンサスアルゴリズムの挙動、スプリットの概念、TrueTimeとの調和、そして物理的なネットワークの制約。これらを頭に叩き込んでいるエンジニアだけが、Spannerのポテンシャルを120%引き出し、数百万QPSを捌く堅牢なシステムを美しく設計できる。

次の設計レビューでは、ただ「Spannerだから安心」と言うのではなく、こう言ってやりたまえ。
「このスキーマだとホットスポットになってPaxosグループのリーダーが死にます。シャードキーを再設計しましょう」と。

君たちのアーキテクチャが、最高のスケーラビリティと強整合性を手に入れることを期待している。

コメント

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