システムデザイン レッスン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 / 3Cache-Asideパターンの動作として正しいものはどれか?