Cloud Spannerの「読み取り専用ステイルネス」を制する者が、スケーラビリティを制す
Cloud Spannerを単なる「リレーショナルデータベース」だと思っているなら、それは大きな勘違いだ。Spannerは「地球規模の分散システム」であり、その真価は、強整合性を維持しながら、どうやって「物理的な距離」と「時間」によるオーバーヘッドをいかにバイパスするかにある。
今回は、Spannerの設計において最も誤解されやすく、かつパフォーマンスを劇的に左右する「読み取り専用のステイルネス(Staleness)」について、現場の視点から深掘りする。
—
1. なぜ「ステイルネス」が重要なのか?
Spannerのデフォルトは「強整合性(Strong Consistency)」だ。これは読み取りのたびに、Paxosグループのリーダーと通信し、最新のタイムスタンプを保証する。しかし、グローバルに展開するアプリケーションにおいて、すべての読み取りでリーダーを叩くのは非効率の極みだ。
ここで登場するのが `TimestampBound` だ。これを使うことで、「あえて少し古いデータを見る」という選択肢が生まれる。この「少し古い」を許容するだけで、読み取りリクエストを最寄りのリードレプリカで完結させることが可能になる。
—
2. 賢いエンジニアが選ぶ「3つのステイルネス・パターン」
実装コードレベルで、どのように使い分けるべきか。主要な3つの設定を整理しよう。
A. `Exact Staleness` (指定した時間前を見る)
「過去の特定のタイムスタンプ」にタイムスリップする設定だ。
// 15秒前のデータにアクセス。
// これにより、読み取りは各レプリカのローカルデータに対して行われる。
TimestampBound bound = TimestampBound.ofExactStaleness(15, TimeUnit.SECONDS);
ResultSet rs = databaseClient.singleUse(bound).executeQuery(statement);
- 使い所: 監査ログの照会、非同期レポート生成、または「データの修正を反映する前の状態」を比較したい場合。
- 注意点: 15秒前を指定しても、その瞬間にレプリカがそのタイムスタンプを持っていなければ、待機が発生する。
B. `Max Staleness` (許容範囲内なら最新を待たない)
「最新である必要はないが、最大でもX秒以内の遅延であれば許容する」という指定だ。
// 最大で10秒以内の遅延を許容。
// レプリカが10秒以内のデータを持っているなら、待たずに即座に返す。
TimestampBound bound = TimestampBound.ofMaxStaleness(10, TimeUnit.SECONDS);
- 使い所: UIのダッシュボード、ランキング表示など。ユーザー体験を損なわない範囲で、ミリ秒単位のレイテンシを削り出したい場合に最適。
C. `Min Read Timestamp` (分散トランザクションの断片化防止)
「指定した時刻以降のデータなら何でもいい」という指定だ。
- 使い所: 一連の処理において、複数の読み取り間で「時間の巻き戻り」を発生させたくない場合。分散トランザクションの整合性を担保しつつ、読み取りを高速化する。
—
3. 実務で「やってはいけない」アンチパターン
現場の設計レビューでよく指摘するポイントを挙げる。
誤解1:「ステイルネスを使えば、常に高速になる」
否。
ステイルネスを設定しても、「レプリカがそのタイムスタンプを持っていない」場合、レプリカは自身が追いつくまで待機する。特にレプリケーションラグが発生している状態で、無理に古いデータを指定すると、かえって待機時間(Latency)が跳ね上がる。
- 教訓: リードレプリカの `ReplicaLag` メトリクスを常に監視しろ。ラグ以上の時間をステイルネスに指定しても無意味だ。
誤解2:「強整合性が不要な場所でも強整合性を使う」
多くのエンジニアは「不安だから」という理由でデフォルトの強整合性を使う。しかし、ユーザーのプロフィール表示やおすすめ商品リストで、1秒の整合性が本当に必要か?
- 教訓: 「ビジネス上の許容範囲」を定義せよ。100msの遅延を許容してステイルネスを設定するだけで、スループットは数倍変わる。
—
4. チーフアーキテクトからの提言
Spannerのステイルネス設定を設計に組み込む際は、以下の「3段階評価」を検討してほしい。
1. 書き込み後の即時参照: ユーザーが自身の更新を確認する画面。→ 強整合性(必須)
2. 集計・分析バッチ: 数秒〜数分の遅延があっても問題ない処理。→ `Exact Staleness` (15s〜)
3. 高速な読み取り重視のUI: ほぼ最新であれば良いランキングやFeed。→ `Max Staleness` (1s〜5s)
最後に:
Cloud Spannerは「魔法の杖」ではない。物理法則(光速の限界とレプリケーションラグ)を正しく理解し、データアクセスの整合性要件を適切にハンドリングする設計者だけが、その性能を極限まで引き出せる。
「とりあえずデフォルト」で設計するのは卒業しよう。読み取りの性質を見極め、ステイルネスを武器にせよ。君たちのシステムは、もっと速く、もっとスケールできるはずだ。
コメント