システムデザイン レッスン3

キャッシュ戦略

レスポンス速度を上げるキャッシュの配置場所と、キャッシュ無効化・整合性の課題への対処法を学ぶ

キャッシュの配置場所

キャッシュは一度計算・取得した結果を一時的に保持し、同じデータへの再アクセスを高速化する仕組みです。 システムの様々な層に配置でき、それぞれ効果と特性が異なります。

Client (Browser Cache)
   |
   v
CDN Cache (静的アセット, 一部API応答)
   |
   v
Application Server
   |  +-- In-Process Cache (プロセス内メモリ)
   |  +-- Distributed Cache (Redis / Memcached)
   v
Database (Query Cache / Buffer Pool)

CDN / ブラウザキャッシュ

画像・JS/CSSなど変化の少ない静的コンテンツに有効。ユーザーに最も近い場所で応答を返せる

分散キャッシュ(Redis等)

複数のアプリケーションサーバーから共有できる。セッションや頻繁に参照されるDB結果に有効

キャッシュ戦略パターン

// Cache-Aside(遅延読み込み) — 最も一般的
function getUser(id):
    cached = cache.get(id)
    if cached: return cached
    user = db.query(id)
    cache.set(id, user, ttl=60)
    return user

function updateUser(id, data):
    db.update(id, data)
    cache.delete(id)   // 更新時はキャッシュを無効化する

// Write-Through — 書き込み時に必ずキャッシュも同時更新
function updateUserWriteThrough(id, data):
    db.update(id, data)
    cache.set(id, data)   // 削除ではなく即座に最新値へ更新

// Write-Behind(Write-Back) — キャッシュへ先に書き、DBへは非同期に反映
function updateUserWriteBehind(id, data):
    cache.set(id, data)
    queue.enqueue({ id, data })  // 後でバッチ的にDBへ反映

キャッシュ無効化と整合性の課題

「computer scienceに残る2つの難問の1つはキャッシュの無効化である」と言われるほど、 キャッシュと元データの整合性を保つのは難しい課題です。

キャッシュの利点

  • • レスポンスタイムの大幅な短縮
  • • データベースへの負荷軽減

新たに生じる課題

  • • 更新の反映漏れによる古いデータの表示
  • • キャッシュ層が増えることによる構成の複雑化

TTLと退避ポリシー

すべてのデータを無期限にキャッシュし続けることはできないため、TTL(有効期限)退避ポリシーを設定します。

  • TTL: 一定時間経過後にエントリを無効化し、次回アクセス時に再取得させる
  • LRU(Least Recently Used): 最近使われていないデータから優先的に削除する退避方式
  • 頻繁に更新されるデータは短いTTL、ほぼ不変のデータは長いTTLを設定するなど、性質に応じて調整する

ポイント

  • キャッシュはブラウザ・CDN・アプリケーション・DBなど複数の層に配置でき、それぞれ特性が異なる
  • Cache-Aside/Write-Through/Write-Behindなど、用途に応じたキャッシュ更新パターンを選ぶ
  • 速度向上と引き換えに整合性の課題が生じるため、TTLや無効化戦略の設計が欠かせない

確認クイズ

1 / 3

Cache-Asideパターンの動作として正しいものはどれか?