【実務・中級編】 監査ログのレイテンシ保証 – Cloud Spanner

いいか、よく聞け。現場のエンジニアが陥りがちな最大の勘違いは、「監査ログなんて、とりあえず標準機能のスイッチを入れれば終わりだ」という甘い考えだ。

Cloud Spannerという、TrueTimeとPaxosの上に築かれた「分散データベースの極北」を扱うなら、その甘さは命取りになる。ミッションクリティカルなシステムにおいて、「トランザクションは成功したが、監査ログが残っていない」あるいは「監査ログを出力したせいで、スループットが半分になった」という事態は、設計者の敗北を意味する。

今日は、Spannerの内部構造から紐解く、監査ログの整合性とレイテンシ保証の「極限の設計」について講義する。

—

1. 監査ログの「所在」を峻別せよ

Spannerにおける監査ログには、大きく分けて2つのレイヤーがある。これを混同しているうちは三流だ。

1. Cloud Audit Logs (Data Access Logs): Google Cloudのインフラ層が吐き出すログ。
2. Application-level Audit Logs: ビジネスロジックとして定義し、Spannerのテーブルに書き込むログ。

今回のテーマである「トランザクションとの整合性」において、真に議論すべきは後者、および前者の「遅延の正体」だ。

2. Cloud Audit Logsの真実:非同期の「壁」

Google Cloudの標準監査ログ(Data Access Logs)は、SpannerのAPI実行に対して「ベストエフォートかつ、ほぼリアルタイム」で生成される。しかし、ここで理解すべきは「Paxosのコミットとログの生成はアトミックではない」という事実だ。

Spannerがクライアントに「Commit成功」を返した瞬間、ログはまだCloud Loggingのバッファの中にいる。この数秒のタイムラグは、金融系のコンプライアンス要件では「監査ログの欠落」と見なされるリスクがある。

  • アーキテクトの知見:

「APIを叩いた事実」を残すだけならこれでいい。だが、「何がどう変わったか(Before/After)」を厳密に、かつトランザクションと不可分に記録したいなら、標準ログに頼るのは素人だ。

3. Change Streams:Spannerが到達した「第三の道」

整合性とパフォーマンスを両立させるための最強の武器、それが Change Streams だ。

Change Streamsは、Spannerの内部的なミューテーション(変更)をキャプチャする仕組みだが、これはPaxosグループのログレプリケーションと密結合している。 つまり、データ本体の書き込みと変更ログの生成は、Spanner内部で極めて高い親和性を持って処理される。

Change Streamsを利用した堅牢なアーキテクチャ

— 監査対象のテーブルにChange Streamを設定する
CREATE CHANGE STREAM AuditLogStream
FOR ALL; — もしくは特定のテーブル、カラムに限定

このストリームをDataflowで拾い、BigQueryや別のSpannerインスタンスに流し込む。

  • 利点: トランザクション本体のレイテンシにほぼ影響を与えない(非同期抽出)。
  • 整合性: Spannerのコミットログから生成されるため、トランザクションが成功してログが残らないという事態は、Spanner自体の崩壊を意味する。つまり、理論上100%の整合性が担保される。

4. 究極の整合性:トランザクション内「ダブル・ライト」の罠と攻略

「監査ログも同一トランザクションで同じテーブル(あるいは別テーブル)に書き込みたい」という要求は、要件定義で必ず出てくる。だが、Spannerでこれを愚直にやると、パフォーマンスが死ぬ。

避けるべきアンチパターン:シーケンシャルなログテーブル

— アンチパターン:挿入順に並ぶログテーブル
CREATE TABLE AuditLogs (
LogId STRING(36) NOT NULL,
CreatedAt TIMESTAMP NOT NULL, — ここがホットスポットになる!
…
) PRIMARY KEY (CreatedAt, LogId);

Spannerはレンジパーティショニングを行う。`CreatedAt`を先頭キーにすると、書き込みが特定のサーバー(スプリット)に集中し、システム全体がスローダウンする。

プロの設計:UUID v4 + 追記型設計

監査ログを同一トランザクションで書き込むなら、以下の3点を死守せよ。

1. Primary Keyの分散: UUID v4を使用し、書き込みを全ノードに分散させる。
2. Mutation Countの意識: Spannerには1トランザクションあたりのミューテーション制限(80,000)がある。ログを細かく書きすぎると、本体のバルク更新を圧迫する。
3. インターリーブの活用: 親テーブルの変更ログなら、親テーブルに `INTERLEAVE IN PARENT` させることで、コロケーション(物理的に同じ場所に配置)を強制し、分散トランザクションのオーバーヘッドを最小化する。

5. レイテンシの正体:TrueTimeがもたらす「待機」

Spannerのコミットレイテンシには、`TrueTime.now()` の不確実性($\epsilon$)を解消するための「コミット待機時間」が含まれる。

監査ログをトランザクションに含めると、書き込むデータ量(Mutation)が増える。これは、Paxosの合意形成に参加するフォロワーへの転送量が増えることを意味する。

  • 知見: Spannerのレイテンシを決定するのは「距離」と「ミューテーションサイズ」だ。
  • 対策: 監査ログに「変更前の値(Old Value)」を無理に詰め込むな。それはChange Streamsに任せろ。トランザクション内では「誰が(Actor)」「何を(Action)」したかという最小限のメタデータに絞れ。

—

結論:テクニカルリードとしての審判

もし君が「監査ログの整合性とレイテンシ」についてレビューを求められたら、こう断言してほしい。

1. 「法的強制力のある証跡」が必要なら、Change Streamsを採用せよ。 これが最もスケーラブルで、Spannerのアーキテクチャに即した正解だ。
2. 「ビジネスロジックとしての即時参照」が必要なログのみ、同一トランザクションで書き込め。 その際は必ずPKを分散させ、ホットスポットを回避すること。
3. Cloud Audit Logsは、あくまで「誰がAPIを叩いたか」という監査の補助として使い、データの整合性担保には使うな。

Spannerは魔法ではない。分散システムの物理法則に従っている。その法則を理解し、Paxosの波を乗りこなす設計をすること。それが、世界最高峰のエンジニアに求められる職人芸だ。

以上だ。次の設計レビューまでに、Change Streamsの保持期間(Retention period)とコスト計算を済ませておけよ。

コメント

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