目次
読了時間: 約8分 | 文字数: 約3,100字
「コンピュータサイエンスには2つの難問しかない。キャッシュの無効化と命名だ」——Phil Karlton のこの言葉は、キャッシュの重要性と難しさを端的に表している。適切なキャッシング戦略は応答時間を100分の1に短縮し、不適切な戦略はユーザーに古いデータを見せ続ける。本稿では、多層キャッシュの設計指針を整理する。
キャッシュの階層構造
Web アプリケーションにおけるキャッシュは、ユーザーに近い順に積み重なる。
ブラウザキャッシュ → CDN → リバースプロキシ → アプリケーションキャッシュ → データベースキャッシュ
上位のキャッシュがヒットすれば、下位への問い合わせは発生しない。この多層構造の設計がパフォーマンスの鍵だ。
ブラウザキャッシュ
最もユーザーに近いキャッシュ。HTTP ヘッダーで制御する。
Cache-Control ヘッダー
Cache-Control: public, max-age=31536000, immutable
public: CDN もキャッシュ可能max-age=31536000: 1年間有効immutable: コンテンツが変わらないことを宣言(再検証リクエストも送らない)
ETag と条件付きリクエスト
# レスポンス
ETag: "abc123"
# 次回リクエスト
If-None-Match: "abc123"
→ 変更なし: 304 Not Modified(ボディなし)
→ 変更あり: 200 OK(新しいコンテンツ)
コンテンツが変わっていなければ転送量ゼロ。帯域幅とサーバー負荷を大幅に削減できる。
CDN キャッシュ
CDN(Content Delivery Network)は世界中のエッジサーバーにコンテンツをキャッシュする。ユーザーから地理的に近いサーバーがレスポンスを返すため、レイテンシが低い。
静的アセットの戦略
CSS、JavaScript、画像ファイルには、ファイル名にハッシュを含めて Cache-Control: immutable を設定する。
styles.a1b2c3.css → Cache-Control: max-age=31536000, immutable
コンテンツが変わればハッシュが変わり、新しい URL になるため、キャッシュ無効化の問題が発生しない。
動的コンテンツの戦略
API レスポンスのキャッシュは短時間にする。max-age=60 で1分間キャッシュし、stale-while-revalidate=300 でバックグラウンド更新を許可する。
アプリケーションキャッシュ(Redis)
Redis はインメモリデータストアで、ミリ秒単位の応答速度を提供する。
キャッシュアサイドパターン
最も一般的なキャッシュパターン。
def get_user(user_id):
# 1. キャッシュを確認
cached = redis.get(f"user:{user_id}")
if cached:
return json.loads(cached)
# 2. キャッシュミス → DB から取得
user = db.query("SELECT * FROM users WHERE id = %s", user_id)
# 3. キャッシュに保存(TTL 300秒)
redis.setex(f"user:{user_id}", 300, json.dumps(user))
return user
ライトスルーパターン
書き込み時にキャッシュと DB を同時に更新する。読み取り時は常にキャッシュがヒットする。書き込みは遅くなるが、読み取りが圧倒的に多いシステムに有効。
ライトバックパターン
キャッシュにのみ書き込み、一定間隔で DB に反映する。書き込み性能は最高だが、キャッシュ障害時にデータを失うリスクがある。
キャッシュ無効化の戦略
キャッシュの真の難しさは無効化にある。
TTL(Time to Live)
一定時間後にキャッシュを自動的に期限切れにする。最もシンプルだが、更新から TTL 期間だけ古いデータが表示される。
イベント駆動無効化
データが更新されたとき、対応するキャッシュキーを明示的に削除する。リアルタイム性は高いが、「どのキャッシュを消すべきか」の管理が複雑。
キャッシュスタンピード防止
TTL 切れの瞬間に大量のリクエストが同時に DB を叩く「スタンピード」問題。ロック機構や確率的早期有効期限切れで対処する。
So What?——実務への応用
- 静的アセットはハッシュ付きファイル名 + immutable: キャッシュ無効化の問題を設計で回避する
- API レスポンスは短い TTL + stale-while-revalidate: 鮮度とパフォーマンスを両立する
- Redis はキャッシュアサイドから始める: パターンが最もシンプルで、問題が起きても DB が正であるため安全
- キャッシュヒット率を監視する: 90% 以下ならキャッシュ戦略の見直しが必要。キーの設計や TTL が適切か検証する
キャッシュは「速くする」ための技術であると同時に、「壊さない」ための注意深い設計が求められる技術だ。何をキャッシュし、いつ無効化するかを明確にすることが、信頼性の高いシステムの基盤となる。
参考リンク
- Redis Documentation — Redis 公式ドキュメント
- MDN - HTTP Caching — HTTP キャッシュの詳細解説
- Cloudflare - CDN の仕組み — CDN の基礎知識
- Caching Patterns — AWS によるキャッシュパターン解説
免責事項 — 掲載情報は執筆時点のものです。料金・機能は変更される場合があります。最新情報は各公式サイトをご確認ください。