AWS / SAP-C02

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 CloudFrontHTTPレスポンス / Webコンテンツ利用者に近い場所から応答し、オリジン負荷を減らす
Amazon ElastiCacheアプリケーションデータ / クエリ結果 / セッション等アプリケーションからデータソースへの反復アクセスを減らす
DAXDynamoDBの読み取り結果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問へ →