TT Lab
はじめる
学ぶ 学習パス コース

Redisとキャッシュ

TTLと期限切れポリシーを扱う

TT Labで続きを見る

目標

TTLの動作を正確に理解し、TTLが静かに消えてしまう落とし穴を再現して防ぎ、エビクションポリシーの違いを、実際のエビクションで確認します。

なぜ重要なのか

「Redisのメモリが増え続けるが、原因がわからない」という問い合わせの大半は、TTLを付けていないキーです。そしてそれが目立たない理由は、コードがSETEXをきちんと使っているのに、どこかでSETで値だけを更新して、もともとあった寿命を消してしまうからです。このラボのステップ3が、まさにその場面です。もう1つ体に残すべきことは、期限切れが即時ではないという事実です。Redisは、アクセスしたときに消すか、バックグラウンドでサンプルを取って消します。そのため、期限切れの時刻が過ぎたキーがDBSIZEに残っていることがあり、「期限切れになったのに、なぜメモリが減らないのか」の答えがここにあります。最後の監査スクリプトは、運用にそのまま持っていって使えるものです。

ステップ

  1. cache:aを値と一緒に60秒の寿命で入れ、/root/ttl/ttl1.txtにttl=<남은초>を書きます(プレースホルダーは残り秒数です)。値は1以上60以下です。
  2. cache:aのTTLを削除します。/root/ttl/ttl2.txtにttl=-1と書かれている必要があります。
  3. cache:bを60秒の寿命で入れたあと、SET cache:b <새값>で値だけを更新します(プレースホルダーは新しい値です)。TTLが-1になることを/root/ttl/lost.txtに記録し、KEEPTTLでもう一度試した結果を/root/ttl/kept.txtにttl=<양수>で書きます(プレースホルダーは正の数です)。
  4. cache:cを1秒の寿命で入れて2秒待ったあと、アクセスしていない状態のDBSIZEとアクセス後のDBSIZEを、/root/ttl/lazy.txtにbefore=<n> after=<n>で書きます。
  5. maxmemory-policyをallkeys-lfuに設定します。/root/ttl/policy.txtにmaxmemory-policy allkeys-lfuが入っている必要があります。
  6. maxmemoryを8mbに下げ、/root/ttl/fill.pyでキーを十分に入れて、エビクションを起こします。/root/ttl/evicted.txtにevicted_keys=<n>を書き、nは0より大きい必要があります。
  7. /root/ttl/audit.shでSCANで走査しながら、TTLが-1のキーを/root/ttl/nottl.txtに書きます。スクリプトにKEYSという文字列があってはならず、結果ファイルに最低1個のキーが必要です。

参考

TTLをかけて残りの寿命を確認する

cache:aを値と一緒に60秒の寿命で入れ、/root/ttl/ttl1.txtにttl=<남은초>を書いてください(プレースホルダーは残り秒数です)。値は1以上60以下です。

寿命を一緒に指定して入れるコマンドもあり、すでにあるキーにかけるコマンドもあります。残りの寿命を取得してみてください。

TTLを削除して永続キーにする

cache:aのTTLを削除してください。/root/ttl/ttl2.txtにttl=-1と書かれている必要があります。

TTLのないキーの取得結果は-1です。-2は別の意味なので注意してください。

SETがTTLを消してしまう落とし穴を再現して防ぐ

cache:bを60秒の寿命で入れたあと、SET cache:b <새값>で値だけを更新してください(プレースホルダーは新しい値です)。TTLが-1になることを/root/ttl/lost.txtに記録し、KEEPTTLでもう一度試した結果を/root/ttl/kept.txtにttl=<양수>で書きます(プレースホルダーは正の数です)。

値だけを更新したのに、寿命が消えます。寿命を維持するオプションがあります。

期限切れが即座のメモリ返却ではないことを観察する

cache:cを1秒の寿命で入れて2秒待ったあと、アクセスしていない状態のDBSIZEとアクセス後のDBSIZEを、/root/ttl/lazy.txtにbefore=<n> after=<n>で書いてください。

期限切れの時刻が過ぎたのに誰もアクセスしていないキーは、しばらく残っています。取得の前後で個数を比べてみてください。

エビクションポリシーを設定する

maxmemory-policyをallkeys-lfuに設定してください。/root/ttl/policy.txtにmaxmemory-policy allkeys-lfuが入っている必要があります。

デフォルト値はキャッシュ用途に合いません。キャッシュ専用ならどのポリシーがよいか、読み物を参考にしてください。

実際にエビクションを起こす

maxmemoryを8mbに下げ、/root/ttl/fill.pyでキーを十分に入れて、エビクションを起こしてください。/root/ttl/evicted.txtにevicted_keys=<n>を書き、nは0より大きい必要があります。

メモリの上限を小さくして、キーをたくさん入れればよいです。エビクションの統計はINFOにあります。

TTLのないキーの監査スクリプトを作る

/root/ttl/audit.shでSCANで走査しながら、TTLが-1のキーを/root/ttl/nottl.txtに書いてください。スクリプトにKEYSという文字列があってはならず、結果ファイルに最低1個のキーが必要です。

SCANで走査しながら、残りの寿命が-1のキーを集めます。運用で定期的に実行できる形である必要があります。