SAP-C02-087 · セクション 10 / タスク 2.5
Caching Strategy
Amazon ElastiCache / Amazon CloudFront / DAX / Cache Hit / TTL / Cache Invalidation
キャッシュは、同じデータやレスポンスを繰り返し生成・取得する代わりに、再利用可能なコピーをより高速な場所へ保持することで、
レイテンシー低下
+
オリジン / データベース負荷低減
+
読み取りスループット向上を狙う仕組みです。
ただし、
キャッシュを追加する
=
必ず高速になるではありません。
重要なのは、
何を再利用できるか
+
どこで再利用するか
+
どこまで古いデータを許容できるか
+
いつキャッシュを捨てるかを決めることです。
つまり、
アクセスパターン
+
再利用率
+
鮮度要件
+
レイテンシー目標
↓
キャッシュ層
+
TTL
+
無効化方式として設計します。
ゴール
次のような要件から、適切なキャッシュ戦略を判断できるようにします。
世界中の利用者へ
同じHTTPレスポンスを配信
↓
Amazon CloudFront
アプリケーションが
同じデータベース結果を反復取得
↓
Amazon ElastiCache
DynamoDBで
結果整合性のある同じ読み取りを反復
+
マイクロ秒級レイテンシー
↓
DAXさらに、
キャッシュヒット
キャッシュミス
TTL
キャッシュキー
キャッシュ無効化の関係から、
性能
と
データ鮮度を両立できるようにします。
1. キャッシュする前に「同じ結果が再利用されるか」を見る
キャッシュの効果は、
同じデータ
または
同じレスポンスが繰り返し要求されるときに大きくなります。
例えば、
商品ID 1001
↓
毎秒数千回参照
商品情報は数分に1回だけ変更なら、毎回データベースから取得する必要性は低くなります。
一方、
リクエストごとに
異なるデータ
一度しか参照されないデータ
常に最新値が必要なら、キャッシュしてもヒットしにくい、またはキャッシュされた値を利用できません。
したがって最初に、
読み取り頻度
ではなく
再利用可能性を確認します。
2. キャッシュヒットとキャッシュミス
キャッシュヒット(Cache Hit)は、要求したデータの有効なコピーがキャッシュ内に存在し、元のデータソースへアクセスせず応答できる状態です。
リクエスト
↓
キャッシュ
│
├─ ヒット
│ ↓
│ キャッシュから応答
│
└─ ミス
↓
オリジン / データベース
↓
データ取得
↓
キャッシュへ保存
↓
レスポンスキャッシュミスでは、最終的にオリジンやデータベースへアクセスするため、
キャッシュヒット
→ 高速
キャッシュミス
→ 元の処理コストが発生となります。
そのため、キャッシュを導入しただけではなく、
どの程度のリクエストが
キャッシュヒットになるかを見る必要があります。
3. キャッシュヒット率だけを最大化しない
キャッシュヒット率が高いほど、一般にオリジン負荷やレイテンシーを減らせます。
しかし、
キャッシュヒット率100%だけを目的にしてはいけません。
例えば商品価格が変更されているのに、
古い価格
↓
長時間キャッシュ
↓
常にキャッシュヒットなら、性能は高くても業務要件を満たしません。
キャッシュでは、
キャッシュヒット率
+
データ鮮度を合わせて考えます。
4. どの層へキャッシュするか
代表的なキャッシュ層は次のように切り分けます。
| キャッシュ層 | 主な対象 | 主な目的 |
|---|---|---|
| Amazon CloudFront | HTTPレスポンス / Webコンテンツ | 利用者に近い場所から応答し、オリジン負荷を減らす |
| Amazon ElastiCache | アプリケーションデータ / クエリ結果 / セッション等 | アプリケーションからデータソースへの反復アクセスを減らす |
| DAX | DynamoDBの読み取り結果 | DynamoDBの結果整合性読み取りをインメモリで高速化する |
同じ「キャッシュ」でも、配置場所が異なります。
利用者
│
▼
CloudFront
│
▼
アプリケーション
│
▼
ElastiCache / DAX
│
▼
データベースCloudFrontはHTTP配信側、ElastiCacheやDAXはアプリケーションのデータアクセス側で使用します。
5. Amazon CloudFrontはHTTPレスポンスをエッジで再利用する
Amazon CloudFrontでは、利用者から同じコンテンツへのリクエストが来たとき、エッジキャッシュに有効なオブジェクトがあればオリジンへ問い合わせず応答できます。
利用者
↓
CloudFrontエッジ
│
├─ キャッシュヒット
│ ↓
│ 利用者へ応答
│
└─ キャッシュミス
↓
オリジン
↓
レスポンス
↓
エッジへキャッシュこのため、
利用者レイテンシー低下
+
オリジンリクエスト削減を同時に狙えます。
CloudFrontは画像やJavaScriptなどの静的コンテンツだけでなく、要件に合えばHTTP APIレスポンスなどもキャッシュできます。
重要なのは、
静的か
動的かだけではなく、
複数の利用者へ
同じレスポンスを再利用できるかです。
6. CloudFrontではキャッシュキーがヒット率を左右する
CloudFrontはキャッシュキーが一致するリクエストを同じキャッシュオブジェクトとして扱います。
キャッシュキーには、必要に応じて、
URL
クエリ文字列
HTTPヘッダー
Cookieなどを含められます。
しかし、レスポンス内容を変えない値までキャッシュキーへ含めると、
同じ商品ページ
Cookie=A
→ キャッシュA
Cookie=B
→ キャッシュB
Cookie=C
→ キャッシュCのように同じ内容のキャッシュが細分化されます。
その結果、
キャッシュミス増加
↓
オリジンリクエスト増加
↓
性能低下につながります。
CloudFront公式ドキュメントでも、レスポンス内容へ影響しないヘッダー、Cookie、クエリ文字列をキャッシュキーから除外することがキャッシュヒット率向上につながると説明されています。
ただし、
Accept-Language
によって日本語 / 英語を返し分けるなど、実際にレスポンスが変わる値はキャッシュキーへ含める必要があります。
つまり、
キャッシュキーを小さくすること自体が目的ではなく、
同じレスポンスになるリクエスト
を
同じキャッシュキーへまとめることが目的です。
7. TTLは性能と鮮度のトレードオフを制御する
TTL(Time to Live)は、キャッシュされたデータをどれだけ長く有効として扱うかを決めます。
基本関係は、
TTL 長い
↓
キャッシュヒットしやすい
↓
元データソースの負荷は減る
↓
古いデータを返す時間は長くなり得るです。
反対に、
TTL 短い
↓
新しい値へ追従しやすい
↓
キャッシュミス増加
↓
元データソースの負荷増加となります。
したがって、
更新頻度
+
許容できる古さ
+
元データ取得コストからTTLを決めます。
例えば、
商品画像
更新は数か月に1回
↓
長いTTLを検討
在庫表示
30秒以上古い値は不可
↓
短いTTL
または
更新時の無効化とします。
8. TTLだけでは即時更新を保証できない
TTLを60分にしたキャッシュで、元データが1分後に変更された場合、
残り59分は古い値が返る可能性があります。
したがって、
変更されたら
すぐ新しい値を返したい場合には、TTLだけではなく、
キャッシュ無効化を検討します。
キャッシュ無効化(Cache Invalidation)は、
このキャッシュは
もう使用してはいけないと明示的にキャッシュを失効させる操作です。
9. ElastiCacheではアプリケーション側のキャッシュ戦略を決める
Amazon ElastiCacheをデータベース前段のキャッシュとして使用する代表的な方法が、遅延読み取り(lazy loading / cache-aside)です。
アプリケーション
↓
キャッシュ確認
│
├─ ヒット
│ ↓
│ キャッシュから返す
│
└─ ミス
↓
データベース
↓
キャッシュへ保存
↓
アプリケーションへ返すこの方式では、
実際に要求されたデータだけがキャッシュされます。
大量の商品データが存在しても、
人気商品100件しか
ほとんど読まれないのであれば、全商品を事前投入する必要がありません。
AWSのElastiCacheドキュメントでも、遅延読み取りを必要なときだけデータをキャッシュする戦略として説明しています。
10. 書き込み時にキャッシュを更新する方法もある
別の方法として、
データベース更新
+
キャッシュ更新を同じ更新経路で行う書き込みスルーがあります。
例えば、
商品価格変更
↓
データベース更新
↓
キャッシュも更新とすれば、次の読み取りで古いキャッシュを返す可能性を減らせます。
一方、
書き込んだが
一度も読まれないデータまでキャッシュすると、不要なキャッシュエントリが増えます。
そのため、
遅延読み取り
+
必要なデータだけ書き込みスルー
+
TTLなど、アクセスパターンに合わせて組み合わせます。
11. ElastiCacheで元データを変更したら古いキャッシュをどうするか
例えば、
RDS
商品価格 = 1,000円
ElastiCache
商品価格 = 1,000円の状態でRDSだけを、
1,200円へ変更すると、
RDS
1,200円
キャッシュ
1,000円になります。
ここでアプリケーションがElastiCacheから読み続ければ、古い値が返ります。
対策には、
更新と同時にキャッシュも更新
更新時にキャッシュキーを削除
短いTTLで自然失効
これらを組み合わせるなどがあります。
つまり、
キャッシュを入れるだけではなく、
元データ更新時
キャッシュをどう扱うかまでがキャッシュ戦略です。
12. Amazon DAXはDynamoDB専用のキャッシュ
Amazon DynamoDB Accelerator(DAX)は、DynamoDB互換のインメモリキャッシュです。
DynamoDB自体は通常1桁ミリ秒の応答を提供しますが、DAXは繰り返される結果整合性のある読み取りをキャッシュから返すことで、マイクロ秒級の読み取りレイテンシーを狙えます。
代表的な要件は、
Amazon DynamoDB
+
読み取り中心
+
反復読み取り
+
結果整合性のある読み取り
+
マイクロ秒級レイテンシー
↓
DAXです。
一方、
RDS
Aurora
DocumentDBなどの汎用キャッシュとしてDAXを使用するわけではありません。
13. DAXには項目キャッシュとクエリキャッシュがある
DAXは大きく2種類のキャッシュを持ちます。
| DAXキャッシュ | 対象 |
|---|---|
| 項目キャッシュ | GetItem / BatchGetItem |
| クエリキャッシュ | Query / Scan |
項目キャッシュでは、
GetItem
↓
キャッシュヒット
↓
DAXから返すとなります。
キャッシュミスの場合はDynamoDBへアクセスし、取得した結果をキャッシュします。
クエリキャッシュでは、
Query条件
+
テーブル / インデックス
などに対応する結果セットをキャッシュします。
現在、DAXの項目キャッシュとクエリキャッシュのデフォルトTTLはいずれも5分です。
14. DAXの項目キャッシュとクエリキャッシュは無効化動作が違う
DAXで特に重要なのが、
項目キャッシュ
と
クエリキャッシュ
は別という点です。
DAX経由で項目を書き込むと、その項目の項目キャッシュは更新されます。
一方、
Query
↓
結果Aをキャッシュ
その後
PutItem
↓
新しい項目追加としても、既に存在するQuery結果のキャッシュは自動的に書き換えられません。
そのQuery結果はTTLが切れるまで古い可能性があります。
したがって、
Query結果に
どの程度の古さを許容できるかからクエリキャッシュTTLを決めます。
15. DAXを経由しない更新にも注意する
アプリケーションAが、
DAX
↓
DynamoDBで読み取っている一方、
アプリケーションBが、
DynamoDBクライアント
↓
DynamoDBへ直接書き込む場合があります。
この場合、
DynamoDB
新しい値
DAX項目キャッシュ
古い値となり、項目キャッシュのTTLが切れるまで差が残る可能性があります。
したがって、
DAXを使用するかだけでなく、
すべての書き込み経路が
どこを通るかも確認します。
16. 強い整合性のある読み取りはDAXでキャッシュされない
DAXは結果整合性のある読み取りの高速化に向いています。
ConsistentRead=trueの強い整合性のある読み取りは、DAXからDynamoDBへ渡されます。
DAXは結果をクライアントへ返しますが、その結果をキャッシュしません。
したがって、
すべての読み取りで
強い整合性が必要というワークロードで、
DAXを入れれば
全読み取りがマイクロ秒級になるとは判断しません。
17. CloudFrontではTTLとオリジンヘッダーの関係を見る
CloudFrontのキャッシュポリシーには、
Minimum TTL
Default TTL
Maximum TTLがあります。
CloudFrontは、オリジンが返す、
Cache-Control
Expiresなどと組み合わせてキャッシュ期間を決めます。
特に重要なのが、
Minimum TTL > 0の場合です。
現在のCloudFrontでは、Minimum TTLが0より大きいと、
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: privateがオリジンから返されても、Minimum TTLの期間はCloudFrontがキャッシュします。
そのため、
個人別レスポンス
機密レスポンス
絶対にキャッシュ不可なら、
オリジンヘッダー
だけを見るのではなく、CloudFront側のキャッシュポリシーも確認します。
18. CloudFrontのキャッシュ無効化
CloudFrontではTTLが切れる前でも、キャッシュされたオブジェクトを無効化できます。
従来から、
/index.html
/images/*
/*のようなパス単位の無効化を利用できます。
無効化後の次のリクエストでは、CloudFrontがオリジンから最新オブジェクトを取得します。
19. 2026年現在はキャッシュタグでもCloudFrontを無効化できる
2026年4月、CloudFrontにはキャッシュタグによる無効化が追加されました。
これにより、
/product/123
/category/keyboard
/recommendations/homeのようにURLパスが異なるオブジェクトでも、
product:123という共通タグを付けておけば、タグを指定して関連オブジェクトをまとめて無効化できます。
商品123を更新
↓
#product:123
を無効化
↓
関連するCloudFrontキャッシュを無効化という設計が可能です。
この機能はCacheTagConfigを設定したディストリビューションで使用します。
これにより、
関連URLをすべて追跡
または
広いワイルドカードで
無関係なキャッシュまで削除する必要を減らせます。
20. 頻繁に更新する静的コンテンツではバージョン付きファイル名も評価する
例えば、
app.jsを同じ名前のまま何度も上書きすると、
古いapp.jsがCloudFront以外のブラウザキャッシュや企業プロキシにも残る可能性があります。
AWSは頻繁に更新するファイルについて、
app-v41.js
app-v42.jsのようなバージョン付きファイル名を使用する方法を推奨しています。
緊急に既存URLを消したい
→ キャッシュ無効化
新しい静的ファイルを継続的にデプロイ
→ バージョン付きファイル名と切り分けます。
21. TTLとキャッシュ無効化は二者択一ではない
実際には、
TTL
+
キャッシュ無効化を組み合わせることがあります。
例えば、
TTL = 1時間
ただし
商品価格変更時
↓
該当キャッシュを即時無効化とすれば、通常時は高いキャッシュヒット率を狙いつつ、
重要な更新にはすぐ追従できます。
逆に、すべての更新で複雑な無効化処理を作るより、
30秒程度の古さを許容できるデータなら、短いTTLだけの方が単純な場合もあります。
22. キャッシュが向かない場合
次のような場合は、キャッシュの効果が小さい可能性があります。
ほぼ全リクエストが異なるデータ
一度しか参照されない
キャッシュ可能な期間が極端に短い
常に強い整合性が必要
個人ごとにレスポンスが大きく異なり
共有キャッシュの再利用率が低い例えば、
100万件のリクエスト
↓
100万件すべて別キー
↓
再利用なしなら、キャッシュ容量を消費してもキャッシュヒットはほとんど起きません。
23. キャッシュとバッファを混同しない
キャッシュは、
過去に取得 / 生成した結果
を再利用する仕組みです。
一方、バッファは、
まだ処理されていない処理要求
を一時的に受け止める仕組みです。
同じ商品情報を
何度も読みたい
→ キャッシュ
大量リクエストを
一度に処理できないので
後段へ順番に渡したい
→ バッファと考えます。
24. キャッシュと読み取りレプリカも同じではない
読み取りレプリカは、データベースの別コピーへ読み取りを分散する方式です。
キャッシュでは、
頻繁に利用される一部データだけを保持することもできます。
また、
キャッシュミスという状態が存在します。
したがって、
キャッシュ
=
読み取りレプリカではありません。
どちらを使うかは、
再利用できるデータか
+
許容する鮮度
+
読み取り負荷
+
アクセスパターンから判断します。
25. シナリオ1:公開APIのオリジン負荷を減らす
要件:
世界中の利用者
+
/catalog API
+
同じレスポンスを多数利用者へ返す
+
2分程度古くても問題なし
+
ALB / アプリケーション負荷を減らしたい判断:
CloudFront
+
HTTPレスポンスキャッシュ
+
TTL 約2分を評価します。
ここでElastiCacheだけを導入しても、
利用者
↓
CloudFront
↓
ALB
↓
アプリケーションまでのリクエスト自体は減りません。
オリジンへのHTTPリクエストそのものを減らすならCloudFront側のキャッシュが重要です。
26. シナリオ2:RDSの人気データだけを高速化する
要件:
RDSに数百万件
+
人気商品だけ繰り返し参照
+
初回ミスは許容
+
未使用データを全部キャッシュしたくない判断:
Amazon ElastiCache
+
遅延読み取りを評価します。
キャッシュヒット
→ ElastiCache
キャッシュミス
→ RDS
→ ElastiCacheへ保存とします。
27. シナリオ3:DynamoDBをさらに低レイテンシー化する
要件:
DynamoDB
+
読み取り中心
+
同一項目を反復
+
結果整合性を許容
+
マイクロ秒級読み取り判断:
DAXを評価します。
逆に、
強い整合性のある読み取り必須なら、DAXのキャッシュヒットを前提にした高速化はできません。
28. 混同ポイント
| 混同 | 正しい判断 |
|---|---|
| キャッシュを置けば必ず高速化する | 再利用率が低ければヒットせず効果は小さい |
| キャッシュヒットが多ければ常に正しい | 古い値を返していないか鮮度も確認する |
| TTLは長いほどよい | ヒット率とデータ鮮度のトレードオフ |
| TTLを設定すれば即時更新できる | TTL前に更新を反映するなら無効化などを検討 |
| CloudFrontは静的ファイルだけ | 再利用可能なHTTPレスポンスもキャッシュ可能 |
| CloudFrontのキャッシュキーには値を多く入れるほどよい | レスポンスへ影響する必要な値だけを含める |
no-storeならCloudFront設定に関係なく絶対キャッシュされない | Minimum TTLが0より大きいとその期間キャッシュされ得る |
| DAXはすべてのDynamoDB読み取りを高速化する | 強い整合性のある読み取りはDynamoDBへ渡されキャッシュされない |
| DAXのQuery結果はPutItemで自動更新される | クエリキャッシュは項目更新では自動無効化されない |
| キャッシュとバッファは同じ | 再利用するデータと未処理の処理要求では目的が異なる |
| キャッシュと読み取りレプリカは同じ | 保持方式・鮮度・アクセスモデルが異なる |
29. SAP-C02での判断フロー
性能ボトルネック
↓
同じデータ / レスポンスが
繰り返し利用される?
│
├─ いいえ
│ ↓
│ キャッシュ以外を評価
│
└─ はい
↓
どこで再利用する?
│
├─ HTTP / エッジ
│ ↓
│ Amazon CloudFront
│
├─ アプリケーションデータ
│ ↓
│ Amazon ElastiCache
│
└─ DynamoDB読み取り
↓
DAX
↓
キャッシュキー / キー設計
↓
許容できる古さは?
↓
TTL
↓
TTL前の更新反映が必要?
│
├─ いいえ
│ ↓
│ TTLによる失効
│
└─ はい
↓
更新 / 削除 /
キャッシュ無効化
↓
キャッシュヒット率
+
元データソース負荷
+
データ鮮度
を測定
↓
性能目標を満たすかまとめ
キャッシュ設計では、
サービス名から考えません。
まず、
同じデータを
繰り返し利用できるかを判断します。
そのうえで、
HTTPレスポンス
→ Amazon CloudFront
アプリケーションデータ
→ Amazon ElastiCache
DynamoDBの反復読み取り
→ DAXとキャッシュ位置を選択します。
そして、
キャッシュヒット
+
キャッシュキー
+
TTL
+
キャッシュ無効化を組み合わせます。
特に重要なのは、
性能
と
データ鮮度の両方を満たすことです。
キャッシュヒットを増やす
だけでも、
常に最新値を取得する
だけでもありません。
どの程度古くてもよいか
+
どの程度オリジン負荷を減らしたいかから最適なキャッシュ戦略を選択します。
主要AWS公式資料
- AWS Certified Solutions Architect - Professional 試験ガイド
- Amazon CloudFront — キャッシュキーを理解する
- Amazon CloudFront — キャッシュポリシーを理解する
- Amazon CloudFront — キャッシュヒット率を増やす
- Amazon CloudFront — ファイルを無効化してコンテンツを削除する
- Amazon CloudFront — キャッシュタグによるコンテンツの無効化
- Amazon ElastiCache — キャッシュ戦略
- Amazon DynamoDB — DAXとインメモリアクセラレーション
- Amazon DynamoDB — DAXとDynamoDBの整合性モデル
- Amazon DynamoDB — DAXクラスターの設定
理解確認
このページの内容を11問で確認します。
理解確認11問へ →