Cloud Spanner内部パフォーマンスメトリクス:スプリットの「呼吸」を聴く者だけが到達できる極限チューニング
おい、設計レビューの手を止めてくれ。
今、君が書いた「Spannerを使っているから勝手にスケールするはずだ」という楽観的な設計、あれを今すぐホワイトボードから消そうか。
Cloud Spannerは魔法の箱ではない。完全無欠の分散RDBである代償として、物理的なハードウェア制約と分散合意プロトコル(Paxos)の厳格な物理法則に支配されている。システムが突如としてレイテンシの壁にぶつかったとき、君は何を見る?CloudWatch…いやGoogle Cloudのモニタリング画面で、ぼんやりと「CPU使用率が80%を超えました」なんてアラートを眺めているだけじゃないだろうな?
チーフアーキテクトとして言わせてもらう。真のSpanner使いは、「スプリット(Split)」単位の呼吸を聴いている。
今回は、Spannerの内部パフォーマンスメトリクスの深淵に潜り、CPU、メモリ、ディスクI/O、そしてネットワーク待機時間が何を語っているのか、実務の現場でどう解釈し、どう設計にフィードバックすべきかを叩き込んでやる。
—
1. スプリット(Split)とは何か? なぜメトリクスの粒度が命取りになるのか
Cloud Spannerのデータは、主キー(Primary Key)の辞書順でソートされ、「スプリット」と呼ばれる連続したキー範囲のチャンクに分割されて物理ノード(厳密にはリーダー/フォロワーのPaxosグループ)に配置される。
デフォルトでは、1つのスプリットはおおむね2GB〜4GB程度、あるいは一定の負荷を超えると自動的に動的分割(Dynamic Splitting)される。
ここでエンジニアが陥る最初の罠がある。
「インスタンス全体のCPU使用率」を見て安心することだ。
インスタンス全体のCPUが40%であっても、特定の「ホットスプリット」にトラフィックが集中していれば、そのスプリットを収容している単一の物理ノード(あるいはそのリージョン内のCPUコア)が飽和し、トランザクションは容赦なくレイテンシを悪化させる。Spannerの内部メトリクスを監視する際、常に意識すべきは「どのスプリットで何が起きているか」という粒度だ。
—
2. コアメトリクスの解剖:CPU、メモリ、ディスク、ネットワーク
内部モニタリング(特に監視コンソールや内部的なエクスポートデータ)で直視すべき主要指標と、その異常兆候をコードレビューの基準として頭に叩き込め。
① CPU利用率 (CPU Utilization)
- 何を測っているか: Paxosグループごとの処理能力の消費度合い。
- 危険な兆候: 特定のスプリットだけが常にCPU 80%超え。
- 原因の特定:
- クエリの非効率性: インデックスのスキャン漏れ、全表スキャン(実質的な全スプリットスキャン)。
- ホットスポット: 連番IDやタイムスタンプを主キーの先頭に置いたことによる、単一スプリットへの書き込み集中。
② メモリ (Memory Pressure / Cache Hit Rate)
- 何を測っているか: Block Cache(データとインデックスのキャッシュ)のヒット率とメモリ消費量。
- 危険な兆候: キャッシュヒット率の急低下、それに伴うディスクI/Oの急増。
- アーキテクチャの知見: Spannerのデータは基本的にメモリ(RAM)上にキャッシュされる。メモリが溢れると、ストレージからの読み込みが発生し、レイテンシが数桁跳ね上がる。特に大量の非効率なRange Scanを行うバッチ処理は、一瞬でキャッシュを汚染(Cache Pollution)させるため殺意を覚えるレベルで警戒すべきだ。
③ ディスク I/O (Disk Storage & IOPS)
- 何を測っているか: ログ書き込み(CommitのためのPaxosログ)とストレージからの読み出し。
- 危険な兆候: 書き込みレイテンシの増大。
- 知見: Spannerの書き込みは、メモリ上への適用と同時に、多数決(Quorum)を取るためにディスク(実際には分散ストレージ層)へのログフラッシュを伴う。ディスクI/Oの待機時間が長い場合、ストレージの限界か、コミット頻度が多すぎる(小さなトランザクションの乱れ打ち)ことが疑われる。
④ ネットワーク待機時間とPaxosレイテンシ (Network Latency / Replication Lag)
- 何を測っているか: リーダーとフォロワー間の同期(Paxosの合意形成)にかかっているラウンドトリップタイム(RTT)。
- 危険な兆候: マルチリージョン構成(マルチプルリージョン)における書き込みレイテンシの肥大化。
- 知見: リーダーがUS、フォロワーが日本にいるような構成で書き込みを行えば、物理的な光速の壁(パケットの伝播速度)に阻まれる。ネットワーク待機時間は、物理的な距離とクロスリージョン・トラフィックの健全性を測る唯一の羅針盤だ。
—
3. 現場で使える!堅牢な設計パターンとアンチパターン
メトリクスが暴れ出したとき、後手に回るようではテクニカルリード失格だ。設計段階でこれらを完全に潰し込む。
アンチパターン:単調増加キーによる「ホットスプリットの生産」
— ❌ 最悪の設計例:IDにUUIDv1やタイムスタンプ、オートインクリメントを使用
CREATE TABLE Orders (
OrderId INT64 NOT NULL, — 常に増え続ける値
CustomerId STRING(64),
CreatedAt TIMESTAMP,
— …
) PRIMARY KEY(OrderId);
何が起きるか:
新しいレコードは常に「最後のスプリット」にしか書き込まれない。Spannerがどれだけ優秀でも、物理的に最後のキー範囲を保持している単一のノードに世界中からの書き込みが集中し、そのスプリットは永遠に分割・移動のループを繰り返すか、CPU飽和で沈没する。
堅牢な設計パターン:ハッシュ化またはプレフィックスによる負荷分散
— ⭕ 推奨される設計例:主キーの先頭に擬似ランダムやハッシュプレフィックスを置く
CREATE TABLE Orders (
ShardId INT64 NOT NULL, — 0からNのハッシュ値(例: 0〜15)
OrderId INT64 NOT NULL,
CustomerId STRING(64),
CreatedAt TIMESTAMP,
— …
) PRIMARY KEY(ShardId, OrderId);
なぜこれで防げるか:
書き込み先が `ShardId` によって16個のスプリットに綺麗に分散される。CPUメトリクスを見たとき、すべてのスプリットが均等にロードを分散して受けている美しいグラフ(フラットな負荷分散)を描くはずだ。これがプロのアーキテクチャだ。
—
4. チーフアーキテクトからの伝言:メトリクスを「予知」に使え
監視とは、障害が起きてからSlackに通知を飛ばすためのものではない。システムの未来の悲鳴を事前に察知するためのセンサーだ。
コードレビューや設計レビューの場で、次のような質問をチームメンバーに投げかけてほしい。
1. 「このクエリ、本番環境でデータが100万件に達したとき、どのスプリットでレンジスキャンを発生させる?」
2. 「このバッチ処理が実行されたとき、Block Cacheのヒット率は何%まで落ち込むと試算している?」
3. 「書き込みのスプリット分散設計(キーの設計)は、ピーク時のスループットに対して十分にスケーラブルか?」
Cloud Spannerの内部パフォーマンスメトリクスを読み解く能力は、単なるツールの使い方ではない。それは、背後でうごめく数千台のマシンと分散合意のアルゴリズムの息吹を、手にとるように感じ取るエンジニアリングの極致なのだ。
さあ、自分たちの設計図を開け。そのキー設計、本当に大丈夫か?
コメント