Cloud Spannerの魂:主キー設計という名の「分散システムへの挑戦状」
Cloud Spannerを単なる「リレーショナルなNoSQL」だと思っているなら、今すぐその認識を改めるべきだ。Spannerの本質は、「分散トランザクションにおいて、いかにして物理的な局所性を制御するか」という極めてハードコアな工学課題に対する、Googleの解答そのものだからだ。
アーキテクトとして、現場で何度も見てきた悲劇がある。「MySQLの感覚で主キーを設計し、スケールアウトの瞬間にシステムが膝を折る」という光景だ。なぜ彼らは敗北したのか。その深淵に迫ろう。
—
1. SplitとDirectory:物理的な「壁」を理解する
Spannerのデータは「Directory」と呼ばれる単位で管理され、さらにそれが「Split」として物理的なノード(Spanner Node)に分散配置される。
ここで重要なのは、「主キーの順序がそのまま物理的な並び順(ソート順)になる」という事実だ。
もし、あなたが `AUTO_INCREMENT` のような単調増加する値を主キーにしたとしよう。すべての新しい書き込みは、辞書順で最後尾に位置する特定のSplitに集中する。そのSplitを保持するノードは、CPUもI/Oも飽和し、他のノードは遊んでいるという、分散システムの死刑宣告を受けることになる。これが「ホットスポット」の正体だ。
知見: Spannerにおける書き込み負荷は、物理的なノードの数ではなく、単一のSplitの処理能力(約2,000〜4,000 QPSが目安)によって制限される。キー設計を誤れば、どれだけノードを増やしてもそのノードは「飾り」で終わる。
—
2. ホットスポット回避の「技術的変遷」
ホットスポットを回避するための古典的、かつ現代的な戦略を整理する。
案A:UUID (v4) の採用
ランダムな値を主キーにすることで、書き込み先を物理的に分散させる。これは極めて有効だが、代償がある。「範囲クエリの破壊」だ。
UUIDを利用すると、時間的な局所性が消滅する。`WHERE created_at > …` のようなスキャンは、複数のSplitを横断することになり、パフォーマンスは劇的に悪化する。
案B:ビット反転 (Bit-reversed sequence)
これは玄人が好む手法だ。単調増加する値をあえてビット反転させ、キーの先頭に持ってくる。
— 概念的な例: シーケンスをビット反転させて先頭に置く
— 物理的にはランダムに分散しつつ、論理的な順序を保つ工夫
CREATE TABLE Orders (
OrderShardKey INT64 NOT NULL, — ビット反転したID
OrderId INT64 NOT NULL, — オリジナルのID
Payload STRING(MAX),
) PRIMARY KEY (OrderShardKey);
この手法の美しさは、「書き込みの分散」と「論理的順序の保持」を両立できる可能性がある点にある。ただし、クエリ側で反転ロジックを実装する必要があるため、アプリケーション層の複雑性は増大する。
案C:キーのハッシュ化(ハッシュパーティショニング)
キーの先頭に、特定の範囲(例: 00-15)のハッシュ値を追加する。
— 物理的に16個のパーティションに分散させる設計
PRIMARY KEY (ShardId, CreatedAt, OrderId)
この「ShardId」を導入することで、特定の時間帯に負荷が集中しても、16個の異なるSplitに負荷が分散される。これが、大規模トラフィックを捌くための「Spannerアーキテクトの定石」だ。
—
3. なぜ「メモリ」が重要なのか
Spannerは、メモリ管理の観点でも極めて洗練されている。
主キー設計が悪いと、特定のSplitのキャッシュ効率が悪化し、頻繁なディスクI/Oが発生する。Spannerは `Colossus` という分散ファイルシステム上に構築されているが、ネットワーク経由のI/Oは依然としてコストが高い。
主キーが適切に分散されていれば、各ノードは自身の担当するデータの「Hot Working Set」をメモリ内に収めることができる。逆に、ホットスポットが発生すると、特定のノードのメモリが溢れ、GC(ガベージコレクション)が頻発し、レイテンシのロングテールが急激に悪化する。
極限の知見:
「分散システムにおいて、データは均一に拡散させよ。ただし、アクセスパターンという名の『文脈』を殺してはならない。」
これが、我々が守るべき唯一の教義だ。
—
結論:アーキテクトへの問い
Spannerの力を引き出すか、あるいはSpannerを単なる高価なRDBMSにしてしまうかは、その主キー設計にかかっている。
1. アクセスパターンを可視化せよ: 範囲スキャンが必要か? トランザクションの競合は発生しないか?
2. 物理構造を意識せよ: そのキーで、書き込みはノード全体に「雨のように」分散するか?
3. 過度な最適化を避けよ: UUIDで全てを解決しようとするな。ビジネスドメインの論理的順序を捨てることは、将来の分析クエリにとって大きな負債になる。
Cloud Spannerは、現代の分散データベースにおける「頂点」だ。この頂点を使いこなすには、SQLの知識だけでなく、データの物理配置を脳内でシミュレートする「分散システム脳」が必要だ。
さあ、設計を見直せ。真のスケールは、テーブル定義の一行目に宿る。
コメント