TTL で一時的なレコードを期限切れにする

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

はじめに

一時的なセッションのレコードは、保存データの削除がまだ行われていなくても、有効期限が切れた時点で提供を止める必要があります。このラボでは、TTL を有効にし、型が誤っている有効期限属性を修正します。さらに、提供されたアプリケーションを設定し、実際のサービスの読み取りで期限切れのデータを除外します。

最初に「注文用の DynamoDB テーブルを作成する」と「パーティションキーとソートキーで注文をクエリする」を完了してください。新しい環境には、独立したセッションテーブル、3 件の架空のレコード、読み取りアプリケーションのひな形が用意されています。TTL と読み取りフィルターを自分で設定します。/home/labex/project、公式 AWS CLI、AWS View を使用してください。このラボでは、TTL の設定と有効期限を考慮した読み取りを評価します。AWS のバックグラウンド削除が完了する期限を保証するものではありません。

認定試験との関連

認定資格 試験タスク 演習内容
Developer – Associate (DVA-C02) タスク 1.3 DynamoDB の TTL 設定と有効期限を考慮した読み取り。
Data Engineer – Associate (DEA-C01) タスク 2.3 基礎演習:DynamoDB の TTL 設定と有効期限を考慮した読み取り。

ラボの概要

AWS4 アイコンを使い draw.io でエクスポートした概念図:TTL は秒単位の Number 型の有効期限属性を使います。提供された読み取りアプリケーションは期限切れセッションを除外し、有効なものと無期限のものを返します。非同期の削除とは別の処理です。

準備済みのセッションテーブルで有効期限を設定する

このステップでは、テーブルの有効期限属性を設定します。Time to Live(TTL)を使うと、DynamoDB は期限切れのアイテムを最終的に削除します。これは非同期の整理処理であり、各アイテムを期限が切れる秒に正確に削除するタイマーではありません。サービスによる削除を待つ間も、アプリケーションは期限切れのデータを拒否する必要があります。

このセッションリーダーでは、レコードをアプリケーションに返せることと、ストレージから削除されたことは別の結果です。TTL の状態を確認し、有効期限の型を修正してから、アプリケーションの結果と直接読み取りを比較します。ENABLED は設定を示します。期限切れのセッションを除外することは読み取り方針を示すもので、サービスによる削除の証明ではありません。

新しい環境のセッションテーブルには、有効なレコード、期限切れのレコード、期限のないレコードという架空のデータが入っています。有効にする前に、それぞれの型と、TTL が無効になっている状態を確認します。

cd /home/labex/project
aws dynamodb scan --table-name labex-d05-sessions --consistent-read
aws dynamodb describe-time-to-live --table-name labex-d05-sessions

expires_at に対して TTL を有効にします。各アイテムが自分の有効期限を持ち、テーブルの設定によって TTL サービスが調べる属性を選択します。属性がないアイテムには、TTL による有効期限はありません。

aws dynamodb update-time-to-live \
  --table-name labex-d05-sessions \
  --time-to-live-specification Enabled=true,AttributeName=expires_at
aws dynamodb describe-time-to-live --table-name labex-d05-sessions

説明に ENABLED と expires_at が表示されたら先に進みます。AWS では、有効になるまで時間がかかる場合があります。ENABLING の間は設定を何度も変更せず、describe コマンドを繰り返してください。上部の AWS View を確認し、セッションのカード内の TTL エントリを展開します。

期限切れレコードの属性の型を修正する

このステップでは、有効な有効期限の値を保存します。DynamoDB TTL には、Unix エポック秒、つまり 1970-01-01 UTC からの秒数を含む Number が必要です。ミリ秒を指定すると、はるか未来の時刻になってしまいます。タイムスタンプに見える文字列でも String 型であることに変わりはなく、TTL 処理はそれを無視します。

正確なキーを指定し、準備された期限切れレコードを確認します。その expires_at は意図的に S で表されています。TTL を有効にしても、この型は修正されません。

aws dynamodb get-item \
  --table-name labex-d05-sessions \
  --key '{"session_id":{"S":"expired"}}' \
  --consistent-read

Linux の date コマンドで、1 時間前の有効期限を計算します。+%s は Unix 秒を出力し、$(...) はその出力を EXPIRED に格納します。値は毎回変わりますが、現在より前である必要があります。

EXPIRED=$(date -u -d '1 hour ago' +%s)
echo "$EXPIRED"

型付きの値を小さな JSON ファイルに入れます。このヒアドキュメントでは、引用符のない JSON 区切りを使うため、シェルが $EXPIRED をタイムスタンプに置き換えます。これまでの引用符付き区切りは、値をそのまま保持していました。JSON をファイルに保存すると、その引用符をエスケープせずに済みます。

cat > expiry-values.json <<JSON
{":expires":{"N":"$EXPIRED"}}
JSON

UpdateItem で有効期限属性だけを置き換えます。file:// は値のファイルを読み込みます。存在条件により、非同期の削除ですでにレコードがなくなっていた場合に、再作成してしまうことを防ぎます。

aws dynamodb update-item \
  --table-name labex-d05-sessions \
  --key '{"session_id":{"S":"expired"}}' \
  --update-expression 'SET expires_at = :expires' \
  --condition-expression 'attribute_exists(session_id)' \
  --expression-attribute-values file://expiry-values.json \
  --return-values ALL_NEW

返された期限切れアイテムの expires_at: {"N": "..."} は過去の時刻を示し、purpose は保持されています。有効なアイテムの期限は未来のままで、期限のないアイテムには引き続き有効期限がありません。AWS で後の読み取りや更新より前にレコードが削除された場合は、接続失敗ではなく、正常なサービスのレスポンスを確認してから削除と判断してください。

アプリケーションの読み取り経路で期限切れデータを除外する

このステップでは、TTL の削除を待つ間の読み取りを保護します。提供された session-reader アプリケーションは、通常の session-reader.json 設定を読み取り、実際の Scan リクエストを実行します。既定の設定では、意図的に期限切れのデータも返します。確認用にアプリケーションのソースが用意されていますが、Python を書く必要はありません。

./session-reader

この環境では、フィルターのない読み取りは、期限切れを含む 3 件すべてのレコードを引き続き返します。これは TTL の設定が誤っている証拠ではありません。AWS のバックグラウンド削除は後で行われる場合があり、正確なスケジュールはこのラボの合格条件に含まれていません。

アプリケーションの有効期限フィルターを有効にします。引用符付きのヒアドキュメントで JSON をそのまま書き込み、設定ファイルを置き換えます。

cat > session-reader.json <<'JSON'
{
  "table": "labex-d05-sessions",
  "filter_expired": true
}
JSON
./session-reader

アプリケーションは、現在時刻を Number 型の秒数で渡す attribute_not_exists(expires_at) OR expires_at > :now を使い、Scan の継続キーをたどります。今度は active と permanent だけが返り、Count は 2、FilterExpired は true になります。permanent レコードを含めるのは意図した動作です。このレコードには有効期限の方針がありません。フィルターにより期限切れデータの提供を防げますが、スキャンの読み取り処理が取り消されるわけではありません。

アプリケーションのフィルターを有効にすると、保存されたレコードが残っていても期限切れデータは除外されます。

キーを指定した直接の読み取りと、アプリケーションの結果を比較します。

aws dynamodb get-item \
  --table-name labex-d05-sessions \
  --key '{"session_id":{"S":"expired"}}' \
  --consistent-read

直接の読み取りには expired がまだ含まれていても、アプリケーションはそれを除外できます。AWS がすでに削除している場合は、正常に成功した空の GetItem も TTL の動作と矛盾しません。AWS View には TTL の設定と、実際の 2 件の読み取り結果が表示されます。フィルターによって保存されたレコードが物理的に削除されたかのように扱うことはありません。

TTL が有効になり、アプリケーションは実際の読み取り結果から期限切れデータを除外しています。

所有するセッションテーブルを削除する

このステップでは、有効期限の設定とアプリケーションの動作を確認した後、明示的にテーブルを削除します。TTL がテーブル全体を削除するのを待たないでください。TTL が削除するのはアイテムであり、テーブル自体ではありません。この使い捨てのテーブルを削除すると、その TTL 設定も削除されます。

aws dynamodb delete-table --table-name labex-d05-sessions
aws dynamodb wait table-not-exists --table-name labex-d05-sessions
aws dynamodb list-tables
aws dynamodb get-item \
  --table-name labex-d05-reference \
  --key '{"id":{"S":"platform"}}' \
  --consistent-read

参照テーブルだけが残り、その note は keep unchanged です。一覧と参照データの読み取りが成功することで、削除後も接続が動作していることを証明できます。AWS View からは、セッションテーブルと読み取り結果が消えます。この使い捨ての接続は、VM とともに終了します。

まとめ

expires_at に対して TTL を有効にし、文字列のタイムスタンプを数値のエポック秒に置き換え、実際のアプリケーションの読み取り経路で期限切れセッションを除外しました。論理的な期限切れと非同期の物理削除を区別し、期限のないレコードは意図的に保持しました。最後に、所有するテーブルを削除し、無関係な参照テーブルを残しました。

詳しくは、AWS 公式ドキュメントを参照してください:TTL の有効期限と項目の非同期削除。