【実務・中級編】 データ配置ポリシーの内部実装 – Cloud Spanner

Cloud Spannerデータ配置ポリシーの内部実装:マルチリージョン時代の物理限界を突破する極限知見

こんにちは。テクニカルリードの私だ。
今日のコードレビュー、あるいはアーキテクチャ設計レビューで、こんなセリフを吐いていないだろうか?

  • 「マルチリージョンだから、なんとなく `nam-eur-asia3` にしとけば安全でしょ」
  • 「レイテンシ? まあグローバル分散なんだから多少遅くなるのは物理の法則として諦めよう」

……もし本気でそう思っているなら、今すぐその設計書を閉じなさい。君たちが使っているのは、単なる「便利なマネージドRDB」ではない。Googleが数十年の分布式データベース研究の粋を集めて構築した、狂気的なまでの整合性とスケーラビリティを持つCloud Spannerだ。

今回は、Cloud Spannerのコアアーキテクチャの根幹である「マルチリージョン構成におけるデータ配置ポリシー(Data Placement Policies)の内部実装」について、物理の限界とPaxosアルゴリズムの泥臭い現実を交えながら、実務で使えるレベルを超えた「極限の知見」として伝授する。

—

1. 原点にして頂点:Spannerの物理トポロジーとPaxosグループ

マルチリージョンのデータ配置を語る前に、Spannerが内部でどうデータを管理しているかを思い出そう。

Spannerのストレージ層は、リレーショナルテーブルではなく、Splits(スプリット)と呼ばれる連続したキー範囲の断片として管理される。そして、それぞれのSplitは高可用性と耐障害性を担保するために、複数のGoogleデータセンターに分散配置されたPaxosグループとして同期される。

マルチリージョン構成において、このPaxosグループのメンバーシップ(レプリカがどのリージョンに配置されるか)を決定するのがデータ配置ポリシーだ。

リーダーレプリカと投票メンバの罠

よくある誤解として、「マルチリージョンならどこでも同じようにデータが読める」というものがある。だが、内部のPaxosの仕組みを理解していれば、それが幻想だと気づくはずだ。

  • リードライト(R/W)レプリカ: トランザクションのコミットにおいて「投票権(Vote)」を持つ。
  • リードオンリー(R/O)レプリカ: 投票権を持たず、TrueTimeAPIを活用してローカルで過去のタイムスタンプのデータをスナップショット読み取りする(リーダーレスの極致)。

マルチリージョン設計の肝は、「書き込み(R/W)のクォーラム(過半数合意)をどの地理的距離の間で形成するか」に尽きる。

—

2. 標準ポリシーの内部挙動と「隠れたレイテンシ」

Googleが提供する標準マルチリージョン構成(例: `nam-eur-asia3` や `us-central1` を含むカスタムマルチリージョンなど)をデプロイする際、内部で何が起きているのか。

クォーラムコミットの物理的限界

R/Wトランザクションをコミットするには、Paxosグループの過半数(Quorum)の承認が必要だ。
例えば、3リージョンにR/Wレプリカを配置する構成を考えてみる。

[リージョンA (東京)] <--- 光速の壁 (約30ms) ---> [リージョンB (大阪)]
\ /
\——- 光速の壁 (約40ms) ————/
[リージョンC (ソウル)]

トランザクションのコミットレイテンシは、「クライアントから最も遠い、過半数を達成するために必要なレプリカまでの往復レイテンシ(RTT)」に下限を縛られる。光速はガラスファイバー中でも約 $2 \times 10^8 \text{ m/s}$。東京・大阪・ソウル間であっても、物理的な伝播遅延(Propagation Delay)はどうあがいても消せない。

> 【チーフアーキテクトの警告】
> 「マルチリージョンだからどこから書いても同じ」という甘い考えは捨てろ。R/Wトランザクションのレイテンシは、最も遠い投票メンバとのラウンドトリップタイムで決まる。不必要にR/Wレプリカの地理的距離を広げることは、自らトランザクション性能を殺しているのと同じだ。

—

3. 実務で直面するアンチパターンと堅牢な設計パターン

では、グローバル展開するシステムにおいて、どのようにデータ配置とクエリを設計すべきか。実戦で使えるパターンを授けよう。

パターンA:マルチリージョン・ライト vs リージョナル・ライトの選択

  • アンチパターン: すべてのテーブルをデフォルトのマルチリージョン(例: `nam-eur-asia3`)で作成し、すべての国からR/W発行する。
  • 結果: 全世界の書き込みレイテンシが数百ミリ秒に跳ね上がり、P99レイテンシが崩壊する。
  • 堅牢な設計パターン(ジオ・パーティショニング / リージョナル分離):

ユーザーのデータ(例: ユーザープロファイル、カート情報)は、そのユーザーが属するリージョン(例: `asia-northeast1`)のリージョナルインスタンス、またはそのリージョンを主座とするマルチリージョンに閉じ込める。

Terraformによる適切なマルチリージョン・インスタンス定義の例

カスタムマルチリージョンを使用する場合、レプリカの役割を明確にコード化する必要がある。

resource “google_spanner_instance” “production_instance” {
config — 組織独自のカスタムマルチリージョン構成を指定
name = “core-db-prod”
display_name = “Core Production DB”
num_nodes = 3

— リージョンごとのレプリカタイプを明示的に制御する
— (※実際にはカスタムコンフィグの定義に準ずる)
}

※実務上の注意: カスタムマルチリージョン構成(Custom Multi-Region Config)設計時は、必ず「リージョン障害時のクォーラム喪失(Split-Brainの防止)」を計算に入れろ。最低3つの独立したリージョン、またはデュアルリージョン+ワットネス(Witness)構成の物理的トポロジーをGoogle Cloudサポートと共に検証必須だ。

パターンB:TrueTimeを活用した「完全ローカル読み取り」の極意

Spannerの真骨頂は、グローバル分散していながら外部一貫性(External Consistency)を担保できる点にある。これをもたらしているのが TrueTime API だ。

マルチリージョン構成でレイテンシを極限まで削るには、読み取り処理をすべてR/Oレプリカ(またはローカルのリードオンリー・トランザクション)にオフロードすることだ。

良いコード例(Java / Cloud Spanner Client)

// 読み取り専用トランザクションを使用し、正確なタイムスタンプ(またはバウンド)を指定
// これにより、ネットワークの向こう側のリーダーにアクセスせず、ローカルのR/Oレプリカから一瞬でデータを引く。
try (ReadOnlyTransaction tx = databaseClient.readOnlyTransaction(
TimestampBound.ofMaxStaleness(Duration.ofMillis(500)))) { // 500ms以内の古いデータを許容する場合

ResultSet resultSet = tx.executeQuery(
Statement.of(“SELECT AccountId, Balance FROM Accounts WHERE Region = ‘AP_NORTHEAST_1′”));

while (resultSet.next()) {
// 処理
}
}

なぜこれが速いのか?
R/Oレプリカは、TrueTimeの不確実性(Uncertainty window, 通常は数ミリ秒)が経過した過去のタイムスタンプを使用するため、他のトランザクションとのロック競合や、遠隔リージョンとの同期通信(Paxosの合意形成)を完全にバイパスしてローカルメモリ/ストレージからデータを読み出せる。グローバル規模であっても、ローカルDB並みの読込レイテンシ(数ミリ秒)を叩き出せる理由はここにある。

—

4. パフォーマンス上の注意点:データ配置ポリシー変更の裏側

「やっぱりデータ配置ポリシーを変えよう」と思ったそこのあなた。本番環境でこれを実行する前に、内部で何が起きるか知っているか?

データ配置ポリシー(コンフィグ)の変更や、テーブル単位のプレースメント(Colocation / Directory)の変更を行うと、Spannerは裏側でバックグラウンドでのデータマイグレーション(Re-sharding & Re-replication)を開始する。

1. 新しいポリシーに従って、新しいPaxosグループのレプリカがターゲットリージョンにプロビジョニングされる。
2. 既存のSplitデータが、新しいリージョン構成へ安全にストリーミング転送される。
3. すべてのレプリカで同期が完了した時点で、トラフィックのルーティングが切り替わる。

このプロセス中、インスタンス全体のスループットやレイテンシに微視的な影響が出ることがある。データ配置ポリシーの変更は、単なる「設定値の変更」ではなく、物理的な地球規模のデータ大移動であるという認識を強く持て。設計段階でユースケースのライフサイクルを見据え、初期段階で完璧な配置を決めておくことがプロのエンジニアの仕事だ。

—

5. チーフアーキテクトからのまとめ

Cloud Spannerのマルチリージョンデータ配置ポリシーは、魔法の杖ではない。それは物理法則(光速とネットワーク遅延)と分散合意理論(Paxos)の制約の中で、最大のパフォーマンスを引き出すための「エンジニアリングのキャンバス」だ。

  • 書き込み(R/W)はコストが高い。 クォーラムに必要な最小限のリージョンに絞り、ジオ・パーティショニングで局所化せよ。
  • 読み取り(R/O)は無限の可能性を秘めている。 TrueTimeとR/Oレプリカを使いこなし、グローバルどこからでもローカルレイテンシを引き出せ。

設計レビューで「なんとなくマルチリージョン」と言っているメンバーがいたら、この記事を叩きつけてやりなさい。そして、物理とアルゴリズムに裏打ちされた、美しい分散アーキテクチャを構築してくれ。

健闘を祈る。

コメント

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