キャッシュ無効化

キャッシュされたデータが古くなった際に、最新のデータに更新または削除する仕組み

キャッシュパフォーマンス

キャッシュ無効化とは

キャッシュ無効化 (Cache Invalidation) は、キャッシュされたデータがソースデータと乖離した際に、キャッシュを最新の状態に更新または削除する仕組みである。Phil Karlton の名言「コンピュータサイエンスで難しいことは 2 つだけ。キャッシュの無効化と命名だ」が示すとおり、正しく実装するのが最も困難なキャッシュの課題だ。

無効化戦略の比較

戦略 仕組み 整合性 複雑さ
TTL 有効期限で自動削除 TTL 内は古いデータ 低い
Write-Through 書き込み時にキャッシュも更新 常に最新 中程度
Write-Behind 書き込みをキャッシュに行い、非同期で DB に反映 最新だが DB 遅延あり 高い
イベント駆動 データ更新イベントでキャッシュを無効化 ほぼ最新 中程度
手動パージ 明示的にキャッシュを削除 操作時のみ最新 低い

TTL ベースの無効化

最もシンプルで広く使われる。キャッシュに有効期限を設定し、期限切れで自動削除する。

// Redis でのキャッシュ + TTL
async function getUser(userId: string): Promise<User> {
  const cached = await redis.get(`user:${userId}`);
  if (cached) return JSON.parse(cached);

  const user = await db.users.findById(userId);
  await redis.setex(`user:${userId}`, 300, JSON.stringify(user)); // 5分 TTL
  return user;
}

TTL 内は古いデータが返る可能性がある。許容できる古さ (Staleness) に応じて TTL を設定する。

イベント駆動の無効化

DynamoDB Streams + Lambda でキャッシュを即座に無効化する。

CloudFront のキャッシュ無効化

デプロイ時に aws cloudfront create-invalidation --paths "/*" で全キャッシュを無効化するのが一般的だ。ただし、インバリデーションはエッジロケーション全体に伝播するまで数分かかる。

より良いアプローチは、コンテンツハッシュをファイル名に含めること (app.a1b2c3.js)。ファイル内容が変わればハッシュが変わるため、インバリデーション不要で即座に新しいファイルが配信される。

よくある失敗パターン

キャッシュとDBの不整合

DB を更新してからキャッシュを更新するまでの間に、別のリクエストが古いキャッシュを読む。対策: キャッシュを「更新」ではなく「削除」する (Cache-Aside パターン)。次のリクエストでキャッシュミスが発生し、DB から最新データを取得する。

Thundering Herd

人気のあるキャッシュキーが TTL 切れになると、大量のリクエストが同時に DB に殺到する。対策: キャッシュの TTL にジッター (ランダムな揺らぎ) を加え、同時に期限切れになるのを防ぐ。

キャッシュ無効化の背景や設計思想は関連書籍に詳しい。

関連用語