Spannerの真髄:TrueTimeが引き裂く「CAP定理の呪縛」とグローバル強整合性の正体
多くのエンジニアが「Spannerは速くて落ちない」という表層的な理解に留まっている中で、我々が対峙すべきは、それがどのような物理法則の限界ギリギリを攻めて実装されているかという深淵だ。
分散データベースにおいて「グローバルな強整合性」を担保することは、かつては不可能に近い聖杯だった。通信遅延、クロックスキュー、そして故障。これらが絡み合う中で、なぜSpannerだけがACIDを維持しつつ、地球規模のスケールを実現できたのか。
今日は、マーケティング資料には決して書かれない、Spannerの核となる「内部メカニズム」を解剖する。
—
1. TrueTime:物理的限界への挑戦
Spannerが強整合性を維持できる最大の理由は、Paxosアルゴリズムそのものではなく、それを支えるTrueTime APIの存在にある。
多くの分散システムは論理時計(Lamport Clockなど)に頼るが、Spannerは物理的な原子時計とGPS受信機をデータセンターに配備し、クロックの「誤差範囲($\epsilon$)」を明示的にAPI化している。
- 絶対時間への忠誠: $TT.now()$ は、ある時点の時刻 $t$ を $[earliest, latest]$ という区間として返す。
- コミット待機(Commit Wait): これが魔法の鍵だ。書き込みトランザクションにおいて、システムは $commit\_timestamp$ が「実際に経過した時間」であることを保証するために、誤差 $\epsilon$ の期間だけ意図的にコミットを遅延させる。
この「待ち」により、書き込みは必ず「現在の世界時刻」よりも先へ行くことが保証される。結果として、「あるタイムスタンプで読み取る」という操作が、地球の裏側であっても全く同じ一貫したスナップショットを指し示すことが可能になるのだ。
2. 内部構造:Paxosと分割の階層
Spannerは、データをDirectoryという単位で管理し、それをTabletにマッピングする。これらは動的に再配置され、Paxosグループを形成する。
ここで熟練のアーキテクトが理解すべきは、「強整合性は、Paxosの過半数合意(Quorum)のコストとどう折り合いをつけているか」だ。
// 概念的なPaxos書き込みプロセス(内部の簡略化モデル)
void ProposeUpdate(Transaction txn) {
// 1. Leaderによるタイムスタンプの割り当て(TrueTimeを使用)
Timestamp commit_ts = TrueTime.now().latest;
// 2. Paxos Groupへの提案。ここで強整合性が担保される。
// 参加するレプリカの過半数がコミットを承認するまで待機。
if (Paxos.Propose(txn, commit_ts)) {
// 3. Commit Wait: 誤差範囲分だけ確実に時間を進める
TrueTime.SleepUntil(commit_ts);
return Success;
}
}
このアーキテクチャの秀逸さは、データのシャーディング(Split)とレプリケーション(Paxos)が直交している点にある。スループットを上げたいなら分割数を増やせばいい。可用性を上げたいならレプリカを増やせばいい。整合性はPaxosのプロトコルレベルで担保されているため、アプリケーション側で「読み取りの不整合」を気にするコードを書く必要は一切ない。
3. メモリ最適化と読み取りの「ゼロコスト」化
強整合性を維持しつつ、リード処理でパフォーマンスを落とさないために、SpannerはSnapshot Readという強力な武器を持っている。
過去のタイムスタンプを指定した読み取り(Stale Read)は、Leaderへの問い合わせを必要としない。これは、各レプリカが持つ「自身の保持しているデータの最新性」を監視するメカニズムによって実現されている。
- Safe Timeの追跡: レプリカは、自身が適用済みのPaxosログのタイムスタンプ(Safe Time)を常に追跡している。
- 局所的な整合性: ユーザーが指定したタイムスタンプ $T$ が、レプリカの $SafeTime$ より小さければ、そのレプリカは自信を持って結果を返せる。Leaderを叩く必要はない。
これにより、グローバルな強整合性を担保しながら、読み取り負荷を全レプリカに分散させるという、矛盾した要求を両立させているのだ。
4. アーキテクトへの提言:Spannerの設計思想を理解する
Spannerを「ただのSQLが動くDB」と呼ぶのは、フェラーリを「ただの移動手段」と呼ぶようなものだ。
我々アーキテクトがSpannerを採用する際、真に考慮すべきは以下の3点である。
1. 書き込みの集中を避ける: TrueTimeのCommit Waitは、スループットの物理的ボトルネックになり得る。ホットなキーに書き込みが集中しないよう、主キーの設計を徹底せよ。
2. 読み取りの特性を活かす: 全てを強整合性で読む必要はない。分析系や参照系は、可能な限り古いタイムスタンプを指定して読み取ることで、レプリカの負荷を最適化せよ。
3. ネットワークトポロジーとPaxos: リーダーの配置とレイテンシは物理法則に従う。マルチリージョン配置において、書き込みがどのリージョンを往復するかを計算し、SLAに合致するようリージョンを選択せよ。
結びに
Spannerは、分散システムにおける「整合性」「可用性」「遅延」というトレードオフの限界を、ハードウェア(原子時計)の力で物理的に押し広げた成果物である。
このシステムの真髄を理解した今、あなたはもう単なるDBユーザーではない。物理層の挙動までを見通し、最強のデータプラットフォームを構築する準備ができたはずだ。
「整合性」とは妥協の産物ではない。設計者の意志そのものである。
コメント