07
第 7 章

キャッシュ設計パターン

この章で学ぶこと
1Cache-Aside パターンの仕組みと適用場面
2Write-Through / Write-Behind パターンの仕組みと使い分け
3キャッシュの無効化戦略と DB との一貫性の考え方
解説

キャッシュの役割

キャッシュ
よく使うデータを高速にアクセスできる場所に一時的に保存する仕組み
目的
データベースへのアクセス回数を減らし、応答速度を向上させる
トレードオフ
速度と引き換えに、データの鮮度(一貫性)を犠牲にする可能性がある
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

Cache-Aside パターンとは

Cache-Aside(Lazy Loading)
アプリケーションがキャッシュの読み書きを制御するパターン
読み取り時
キャッシュを確認 → ミスなら DB から取得 → キャッシュに格納
書き込み時
DB に書き込み → キャッシュを削除(または更新)
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

Cache-Aside の流れ

読み取りフロー: ヒット時とミス時の 2 つの経路

キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

Cache-Aside のメリットとデメリット

メリット
必要なデータだけがキャッシュされる(メモリ効率)/ Redis ダウン時も DB から取得可能(耐障害性)
デメリット
初回アクセスは必ずキャッシュミス(コールドスタート)/ キャッシュと DB の間にデータのずれが生じうる
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

実演環境 — Cache-Aside の構成

7-05_cache-aside-compose
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
実演

Cache-Aside の動作確認

目的Cache-Aside パターンの動作をアプリケーションで確認する
操作docker compose up → データ取得(ミス → ヒット)→ Redis CLI で確認
確認する
ポイント
キャッシュミス時とヒット時の応答速度の違い
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

Write-Through パターンとは

Write-Through
書き込み時にキャッシュと DB を同時に更新するパターン
書き込み
アプリ → キャッシュに書き込み → DB にも書き込み(同期)
読み取り
キャッシュから直接取得
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

Write-Through の流れ

書き込み時にキャッシュと DB を同期的に更新するフロー

キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

Write-Behind パターンとは

Write-Behind(Write-Back)
キャッシュに書き込み、DB への反映は非同期で行うパターン
書き込み
アプリ → キャッシュに書き込み → 非同期で DB に反映
DB への書き込みを遅延
書き込み性能を向上させる
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

Write-Behind の流れ

キャッシュのみ同期、DB への反映は非同期で行うフロー

キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

3 パターンの比較

観点
Cache-Aside
Write-Through
Write-Behind
読み取り性能
ミス時は遅い
常に高速
常に高速
書き込み性能
DB のみ
やや遅い(2 箇所同期)
高速(キャッシュのみ)
一貫性
TTL 依存
強い
弱い(遅延あり)
データ消失
なし
なし
あり(Redis ダウン時)
実装の複雑さ
低い
中程度
高い
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

パターン選択の判断基準

読み取りが多く、シンプルに始めたい
→ Cache-Aside
書き込みの直後に最新データを読みたい
→ Write-Through
書き込みが多く、性能が最優先
→ Write-Behind(データ消失を許容できる場合)
迷ったら Cache-Aside から始める
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

実演環境 — Write-Through の構成

7-06_write-through-compose
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
実演

Write-Through の動作確認

目的Write-Through パターンの動作をアプリケーションで確認する
操作docker compose up → データ書き込み → 読み取り → Redis CLI と DB で確認
確認する
ポイント
書き込み直後にキャッシュと DB の両方にデータがあること
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

実演環境 — Write-Behind の構成

7-07_write-behind-compose
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
実演

Write-Behind の動作確認

目的Write-Behind パターンの動作をアプリケーションで確認する
操作docker compose up → データ書き込み → Redis CLI で確認 → DB で確認(遅延反映)
確認する
ポイント
キャッシュと DB の反映タイミングの差
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

キャッシュの無効化とは

キャッシュの無効化
キャッシュに保存されたデータを削除または更新して、古いデータが使われ続けることを防ぐ操作
Phil Karlton の名言
「キャッシュの無効化はコンピュータサイエンスで最も難しい問題の 1 つ」
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

TTL ベースの自然失効

TTL ベースの自然失効
キーに有効期限を設定し、期限切れで自動的にキャッシュを削除する
メリット
実装がシンプル。追加のロジックが不要
デメリット
TTL が切れるまで古いデータが返される可能性がある
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

イベント駆動の明示的無効化

イベント駆動の無効化
DB が更新されたタイミングで、対応するキャッシュを明示的に削除する
方法
DB の更新処理の直後に Redis の DEL コマンドを実行する
メリット/デメリット
データの鮮度が高い / DB 更新のたびにキャッシュ操作が必要(実装の複雑さが増す)
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
図解

不整合が起きるシナリオ

DB 更新とキャッシュ削除の間に別のリクエストが来ると古いデータが返される

キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

「完全な一貫性は求めない」という設計判断

キャッシュを使う時点で完全な一貫性は諦めている
「どの程度の不整合を許容するか」を明確にする
結果整合性(Eventual Consistency)
時間が経てばいずれ最新のデータに収束する
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
解説

キャッシュスタンピード

キャッシュスタンピード
キャッシュの期限切れ直後に、大量のリクエストが同時に DB に殺到する現象
発生条件
アクセス頻度が高いキーの TTL が切れたとき
対策
TTL にジッター(ランダムな揺らぎ)を加える
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
コマンド

キャッシュスタンピードの対策

base_ttl = 300          # 基本 TTL: 5 分jitter = random(0, 60)  # 0〜60 秒のランダム値$ SET key value EX (base_ttl + jitter)
分散ロック1 つのリクエストだけが DB に問い合わせ、他は待機する
確率的早期再計算期限切れ前にランダムにキャッシュを更新する
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ
まとめ

この章のまとめ

Cache-Aside: アプリがキャッシュを制御。読み取りが多い場面に。迷ったらまずこれ
Write-Through: キャッシュと DB を同時更新。一貫性が重要な場面に
Write-Behind: キャッシュのみ書き込み、DB は非同期。データ消失リスクあり
無効化: TTL ベースとイベント駆動を組み合わせる
設計判断: 完全な一貫性は求めず、許容できる不整合の範囲を明確にする
次章: ユースケースとアーキテクチャパターン
キャッシュの役割
Cache-Aside
Write-Through
Write-Behind
パターン比較
無効化
不整合と一貫性
スタンピード
まとめ