【実務・中級編】 レプリカの種類と役割 – Cloud Spanner

【Cloud Spanner 徹底解説】レプリカの内部構造を熟知せずして、真の分散設計は語れない

こんにちは。チーフアーキテクトの私だ。
今日のコードレビューや設計レビューで、こんなやり取りを見かけなかったか?

「とりあえずマルチリージョン構成にしておけば可用性は完璧だよね?」
「Stale Read(古いデータの読み取り)? なんか難しそうだから、とりあえず強整合性(Strong Read)で全部叩いとけばいいか」

――待て。その設計、本当にプロダクションのトラフィックに耐えられるか?

Cloud Spannerは、リレーショナルデータベースの美しさと、NoSQLの水平スケーリングを極限の次元で融合させた怪物的なシステムだ。だが、その内部で何が起きているのか(特にレプリカの種類と役割)を理解せずに使うのは、目隠しをしたまま超音速ジェット機を操縦するようなものだ。

今回は、Spannerのコアアーキテクチャの心臓部である「リーダー」「フォロワー」「ウィットネス」の3つのレプリカに焦点を当て、合意形成(Paxos)、読み書きのルーティング、そして我々エンジニアが実務でどう設計に落とし込むべきかを、一切の妥協なく叩き込む。

—

1. Spannerの物理・論理構造の前提:スプリットとPaxosグループ

まず前提を共有しよう。Spannerのデータは、単一の巨大なディスクに保存されているわけではない。テーブルの行(Row)は、主キーの範囲に基づいて「スプリット(Split)」という動的なシャードに分割される。

各スプリットは、単一のマシンではなく、複数のノードにまたがる「Paxosグループ(Paxos Group)」として管理される。データの書き込みや読み込みが発生したとき、私たちが相手にしているのはデータベース全体ではなく、このスプリット単位のPaxosグループなのだ。

そして、このPaxosグループを構成するのが、以下の3種類のレプリカである。

—

2. 3種類のレプリカ:その定義と「権能」

それぞれのレプリカが持つ「役割」と「権能」を正確に把握しているか? ここを曖昧にしていると、レイテンシの罠や可用性の勘違いに足元をすくわれる。

[Paxosグループの物理配置イメージ(例: マルチリージョン)]
リージョンA リージョンB リージョンC
+—————-+ +—————-+ +—————-+
| Leader Replica | | Follower Rep. | | Witness Rep. |
| (Write/Read) | | (Write/Read) | | (Vote Only) |
+—————-+ +—————-+ +—————-+

① リーダーレプリカ (Leader Replica)

  • 定義: Paxosグループの主権を握る中核ノード。
  • 役割:
  • すべての書き込みトランザクション(Write)のオーケストレーション。
  • 強整合性読み取り(Strong Read)のコーディネート(TrueTime APIとの連携)。
  • 知見:

リーダーは固定ではない。負荷分散や障害発生時には、Paxosのリーダー選挙(Leader Election)によって動的に別のノードにリーダー権限が移譲される。一つのSpannerインスタンス内でも、スプリットAのリーダーはノード1だが、スプリットBのリーダーはノード5、といったことが常時発生している。

② フォロワーレプリカ (Follower Replica)

  • 定義: データの完全なコピーを保持しつつ、リーダーの主導するPaxos合意に参加するノード。
  • 役割:
  • 書き込み時のPaxosプロトコルにおける「過半数の同意(Quorum)」の形成。
  • ローカルな読み取り(Stale Read / Bound Staleness)の処理。
  • 知見:

フォロワーは、単なる「バックアップ」ではない。リージョン分散構成において、クライアントの近く(ローカルリージョン)にフォロワーを配置することで、書き込みのレイテンシを最小化しつつ、Stale Readであればリーダーを介さずに高速かつ無限にスケールする読み取りを提供できる。

③ ウィットネスレプリカ (Witness Replica)

  • 定義: データ(実ペイロード)を持たず、Paxosの投票権(Vote)だけを持つ特殊なレプリカ。
  • 役割:
  • Paxosグループにおける「過半数(Quorum)」を形成するための頭数としての参加。
  • 知見:

「なぜデータを持たないノードが存在するのか?」――ここにSpannerのアーキテクチャの美しさがある。
例えば、可用性を高めるために「3つのリージョン」にレプリカを置きたいとする。しかし、すべてのリージョンにフルデータ(フォロワー)を置くと、ストレージコストが3倍になるだけでなく、広域ネットワーク間でのデータ同期コストも跳ね上がる。
そこで、3つ目のリージョンにはウィットネスを置く。データは持たないが「書き込みの合意(投票)」には参加するため、「2つのデータ保持ノード + 1つのウィットネス」で、最小限のコストで「過半数(2/3)」による耐障害性を担保できるのだ。

—

3. 合意形成(Paxos)と読み書きの裏側

ここで、データの書き込みが起きたときに、これら3者がどう動くのかを解剖する。

1. 書き込み要求の発生: クライアントがリーダーレプリカに書き込みを投げる。
2. Paxosプロトコル(提案と合意):

  • リーダーは、変更ログをフォロワーおよびウィットネスにブロードキャストする。
  • フォロワーとウィットネスは、ログを受け取り、ディスクへの書き込み(フォロワー)または単なる投票(ウィットネス)を行い、「同意(Ack)」を返す。
  • 過半数(Quorum)からのAckを得た時点で、リーダーはその書き込みを「コミット(確定)」とみなす。

3. TrueTimeとの同期: コミットタイムスタンプが、Googleの原子時計とGPSによって保証された「TrueTime(不確実性 $\epsilon$ を持つ時間範囲)」に基づいて付与される。

この仕組みにより、物理的に地球の裏側に離れたデータセンター間であっても、ACID特性を完全に満たしたグローバル分散トランザクションが成立しているのだ。

—

4. 実務で活かす!堅牢な設計パターンとアンチパターン

さて、ここからが本題だ。このレプリカの挙動を踏まえ、私たちは実際のシステム設計でどう立ち回るべきか。

【設計パターン 1】読み取り専用トラフィックは「Stale Read」を積極的に活用せよ

  • 背景: すべてのSELECTクエリに強整合性(Strong Read)を要求すると、すべてのクエリがリーダーレプリカ、あるいはリーダーとの同期を伴う経路を通るため、リーダーに負荷が集中する。
  • 対策: 「直近数秒のデータでも業務上問題ない(例: 商品一覧、プロフィール情報、アナリティクス集計)」画面やAPIでは、`ExactStaleness` や `MaxStaleness` を指定した Stale Read を実装せよ。
  • 効果: クライアントに最も近いフォロワーレプリカでクエリが完結するため、リーダーの負荷が劇的に軽減され、レイテンシが数分の一に低下する。

// Java (Cloud Spanner Client) を用いたStale Readの例
TimestampBound bound = TimestampBound.ofExactStaleness(15, TimeUnit.SECONDS);
// この読み取りは、リーダーをバイパスし、ローカルのフォロワーレプリカで高速に処理される
ResultSet resultSet = dbClient.singleUse(bound)
.executeQuery(Statement.of(“SELECT FROM Products WHERE CategoryId = 1”));

【設計パターン 2】マルチリージョン構成での「コスト対可用性」の最適化

  • 背景: 災害対策(DR)やグローバル展開を考慮し、マルチリージョン構成にする際、何も考えずにフルレプリカを並べると莫大なコストがかかる。
  • 対策: リージョン構成(Configuration)の選定において、ウィットネスレプリカの特性を理解した上で選択する。例えば、Google Cloudが提供するリージョン構成(例: `nam-eur-asia1` などのマルチリージョン)では、書き込み可用性を担保するために適切な数のフォロワーとウィットネスが背後で自動配置されている。
  • 注意: 自前でカスタムインスタンス構成を組む場合、ウィットネスを配置するリージョンのネットワーク特性や障害ドメインを綿密に計算し、真の過半数割れ(Quorum Loss)が起きない配置にしなければならない。

【アンチパターン】「なんとなくマルチリージョン」による書き込みレイテンシの爆発

  • 背景: 「グローバル展開するから、アメリカとヨーロッパとアジアにレプリカを置こう」と安易に設計する。
  • 現実: Paxosの合意形成には「物理的な往復レイテンシ(Speed of light)」の壁が立ちはだかる。地球の裏側との通信にはどうあがいても数千ミリ秒の物理的限界がある。
  • 教訓: 書き込み(Write)のパフォーマンスは、主にリーダーとフォロワー間の物理的距離に依存する。書き込み性能を最大化したければ、主要なトラフィック元にリーダーやフォロワーを集中させ、遠隔地にはウィットネスやStale Read用のフォロワーを配置する設計的割り切りが必要不可欠だ。

—

5. チーフアーキテクトからの提言

Cloud Spannerは「魔法の箱」ではない。物理法則と分散システムの厳格な理論(Paxos、FLP不可能性定理、TrueTimeによる外部整合性)の上に成り立っている精巧なエンジンだ。

  • リーダーは「書き込みと強整合性の司令塔」
  • フォロワーは「データ保持とローカル読み取りの要」
  • ウィットネスは「最小コストで可用性を守る無私の投票者」

この3者の役割をコードやクエリの挙動レベルでイメージできるようになれば、あなたの設計レビューにおける発言の説得力は劇的に変わるはずだ。

「なぜこのクエリはStale Readにできないのか?」
「このマルチリージョン配置におけるPaxos Quorumはどう担保されているのか?」

――自信を持って、これらの問いに答えられるエンジニアであれ。
次回の設計レビューを楽しみにしている。

コメント

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