TTL と無効化でキャッシュを更新する

RedisBeginner
オンラインで実践に進む

はじめに

商品キャッシュはソース読み取りを減らしますが、ソースが変わるとキャッシュ価格が古くなることがあります。その期間を観察し、値が期限切れになるのを待ち、明示的な無効化によってアプリの更新をすぐに反映します。

「商品検索にキャッシュを追加する」を先に完了してください。この新しい環境には同じ商品アプリ、DynamoDB カタログ、接続済み Valkey ノードが独立して用意されています。Terminal で通常の AWS CLI とアプリコマンドを実行し、AWS View でソースと応答を比較します。前の VM のリソースは使いません。

認定試験との関連

認定 試験タスク 実践
Cloud Practitioner (CLF-C02) Task 3.4 メモリー内キャッシュと正本データを区別し、アプリの動作を観察する。

このラボの概念図

TTL の期限切れで価格を更新する

このステップでは、古いキャッシュ価格と期限切れ後の更新を観察します。TTL(time to live)はキャッシュ値が利用できる時間を制限します。期限切れはキャッシュのコピーを削除し、DynamoDB の正本項目は削除しません。

準備された ID とアプリ設定を確認します。

cd /home/labex/project
aws sts \
  get-caller-identity
cat app.json

ARN の末尾は labex-ca02-operator です。アプリは既に cache-aside を使用し、商品 101 の最初の価格は 20.00 です。接続先キャッシュのエンドポイントを保存して表示します。

CACHE_HOST=$(jq -r .cache_host app.json)
echo "$CACHE_HOST"

短い実験には5秒の TTL を使います。新たなキャッシュ書き込みは設定した TTL を使いますが、設定変更は既存キーに遡って適用されません。

jq '.ttl_seconds = 5' app.json > app.next.json
mv app.next.json app.json

次のブロックは時間に依存する1つの実験です。続けて実行してください。元の商品を読み、ソースを直接更新し、5秒の有効期間が終わる前に商品をすぐに再読します。直接の AWS 更新は DynamoDB を変更しますが、アプリのキャッシュには通知しません。

curl -sS http://127.0.0.1:8080/api/products/101
aws dynamodb \
  update-item \
  --table-name product-catalog \
  --key '{"product_id":{"S":"101"}}' \
  --update-expression 'SET price = :price' \
  --expression-attribute-values '{":price":{"N":"21.00"}}' \
  --return-values ALL_NEW
curl -sS http://127.0.0.1:8080/api/products/101

ソース更新は 21.00 を返しますが、直後のキャッシュ応答は served_from: cache と古い 20.00 を返します。AWS View は新しいソースレコードと現在の設定を表示します。データベース更新の成功はキャッシュの自動無効化を意味しません。

TTL より長く待って新しいリクエストを送ります。

sleep 6
curl -sS http://127.0.0.1:8080/api/products/101

応答はソースから 21.00 を返します。期限切れ値がなくなったため、アプリは DynamoDB を読み、新しい値を保存しました。すぐに問い合わせれば残り時間を観察できます。

valkey-cli -h "$CACHE_HOST" -p 6379 TTL product:101

正の値は残りの存続時間、-2 はキーが既に期限切れであることを示します。この短い TTL は学習で鮮度を観察するための値で、本番の推奨値ではありません。本番 TTL は許容できる古さの期間に依存します。 有効期限後の AWS View の例:ソースと応答は 21.00、TTL は5秒です。読み取り数は異なる場合があります。

更新した商品をすぐに無効化する

このステップでは、アプリの更新経路から変更対象の商品だけを無効化します。無効化はキャッシュコピーを削除し、次のリクエストで現在のソースを読ませます。TTL を待つ代わりに、既知の更新を即時に反映できます。

HTTP PUT はアプリに新しい価格を送ります。アプリはまず DynamoDB を更新し、対応するキャッシュキーを削除します。現在の商品をキャッシュし、更新して2回読む次の一連の操作を続けて実行してください。5秒の TTL の実験を観察可能にするためです。

curl -sS http://127.0.0.1:8080/api/products/101
curl -sS -X PUT \
  -H 'Content-Type: application/json' \
  --data '{"price":"22.00"}' \
  http://127.0.0.1:8080/api/products/101
curl -sS http://127.0.0.1:8080/api/products/101
curl -sS http://127.0.0.1:8080/api/products/101

更新は invalidation_key: product:101 と通常 removed: 1 を返し、実際のキー削除を示します。更新前に期限切れなら removed: 0 はコピーが残っていないことを示しますが、正しい無効化キーを使う必要は変わりません。次の検索はソースから 22.00、その次はキャッシュから 22.00 を返します。明示的な無効化は TTL を補完し、読み取りと同じキーを使う必要があります。

商品 202 はこの更新とは無関係です。ソースが引き続き価格 12.50 の Notebook であることを確認します。

aws dynamodb \
  get-item \
  --table-name product-catalog \
  --key '{"product_id":{"S":"202"}}' \
  --consistent-read

確認のため更新後のアプリを稼働させたままにします。チェックは実際のリクエスト結果とソースを読み、短い TTL 後にキーが残っていることは要求しません。 アプリ更新後の AWS View の例:価格は 22.00、Notebook は不変です。短い TTL の後はソースを再読する場合があります。

まとめ

ソースを直接更新した後の古いキャッシュ応答、TTL 期限切れ後の更新、対象キーの無効化後の即時更新を観察しました。ソースが正本です。TTL は古い期間を制限し、アプリの更新経路は正確な読み取りキーを無効化します。

詳しくは、AWS 公式ドキュメントを参照してください:TTL と許容できるキャッシュの古さ; Valkey の TTL 戻り値。