判断: どのキャッシュ戦略か?
キャッシュは頻繁に読み取られるデータをデータベースの前段の高速な層 (例: Redis) に保持し、レイテンシと DB の負荷を下げる。ただし、すべてのデータがキャッシュに適しているわけではなく、誤った無効化は古い/不正確なデータのリスクを生む。このツリーは、まずキャッシュが本当に必要かを確認し、その上で読み書きのパターンに基づいて cache-aside、read-through、write-through、write-behind の中から選択を支援し、スタンピードの防止も扱う。
ワークロードはどのような傾向か: 読み取り中心か、書き込み中心か?
キャッシュが最も効果を発揮するのは、同じデータが何度も読み取られ (読み取り中心)、頻繁に変更されない場合。まず全体的なパターンを把握する: データは頻繁に読まれ、まれにしか変更されないのか、常に更新されるのか、それともキャッシュを追加する価値があるかどうか確信がないのか?
- 非常に読み取り中心で、データの変更は比較的まれ
- 書き込みも多い。書き込まれたデータがすぐに/頻繁に読み取られる
- 確信がない。本当にキャッシュが必要か?
キャッシュへのデータ投入は誰が担うべきか?
読み取り中心のシナリオでの重要な選択は、誰がキャッシュにデータを投入するか。アプリケーションがキャッシュを明示的に管理し、自ら DB にフォールバックすべきか (柔軟性が高い)、それともキャッシュ層がミス時にバックエンドの DB からデータを取得し、透過的に返すべきか?
- アプリケーションが明示的に管理する。柔軟性と制御性が欲しい
- ミス時にキャッシュ層が DB から取得する (透過的)
書き込み時は、一貫性と書き込み速度のどちらが優先か?
書き込みが多い場合、書き込まれたデータのキャッシュと DB 間の一貫性をどの程度にするかを決める必要がある。書き込みごとにキャッシュと DB を同時に更新して一貫性を保証すべきか (書き込みはやや遅くなる)、それとも書き込みをまずキャッシュに行い、バックグラウンドで非同期に DB へ反映すべきか (書き込みは非常に高速だが損失リスクがある)?
- 一貫性が重要。読み取りは常に最新でなければならない
- 書き込み速度が重要。一貫性の多少の遅れと損失リスクは許容できる
推奨: 現時点ではキャッシュを追加しない
キャッシュは無償ではない: 一貫性の問題 (古いデータ)、追加のインフラ、無効化の複雑さをもたらす。クエリがすでに高速な場合や、データがリクエストごとに変わる場合、キャッシュは利点をもたらさず、障害要因を増やすだけ。
推奨: cache-aside (遅延ロード)
cache-aside では、アプリケーションがまずキャッシュを確認し、データがない場合 (ミス) は DB から読み取ってキャッシュに書き込み、返す。最も一般的で柔軟なパターンであり、キャッシュには実際に要求されたデータのみが格納される。
推奨: read-through キャッシュ
read-through では、アプリケーションはキャッシュとのみやり取りし、ミス時にはキャッシュ層自体が DB からデータを取得して投入する (プロバイダ/ローダー経由)。アプリケーションコードがシンプルになり、投入ロジックが 1 か所に集約される。
推奨: write-through キャッシュ
write-through では、すべての書き込みがキャッシュと DB の両方に (同期的に) 行われ、両方が同時に更新される。そのため、キャッシュが DB より遅れることはなく、読み取りは常に最新のデータを参照する。
推奨: write-behind (write-back) キャッシュ
write-behind では、書き込みはまずキャッシュに行われ、直ちにユーザーに応答が返る。DB への書き込みはバックグラウンドで非同期に (バッチ化/遅延して) 行われる。書き込み速度は最も高いが、耐久性と一貫性のリスクを伴う。