TT Lab
开始
学习 学习路径 课程

Redis 与缓存

处理 TTL 与过期策略

在 TT Lab 中继续学习

目标

准确理解 TTL 的行为,重现并阻止 TTL 悄悄消失的陷阱,并通过实际的驱逐来确认驱逐策略之间的差异。

为什么重要

“Redis 内存一直在增长,却找不到原因”这类咨询,大部分都是没有设置 TTL 的键。而它之所以不显眼,是因为代码明明在好好地使用 SETEX,却在某处用 SET 只更新了值,把原本的生存时间抹掉了。本实验的第 3 步正是这一幕。还有一件要刻进脑子里的事:过期并不是立即发生的。Redis 要么在访问时删除,要么在后台抽取样本来删除。所以过期时间已过的键可能仍留在 DBSIZE 里,“明明过期了,为什么内存没有减少”的答案就在这里。最后的审计脚本可以原样带到生产环境中使用。

步骤

  1. 把 cache:a 连同值一起以 60 秒的生存时间放入,并在 /root/ttl/ttl1.txt 中写入 ttl=<남은초>(占位符为剩余秒数)。该值必须大于等于 1 且小于等于 60。
  2. 移除 cache:a 的 TTL。/root/ttl/ttl2.txt 中必须写有 ttl=-1。
  3. 以 60 秒的生存时间放入 cache:b 之后,用 SET cache:b <새값>(占位符为新值)只更新值。把 TTL 变成 -1 的情况记录到 /root/ttl/lost.txt,再把用 KEEPTTL 重试的结果,以 ttl=<양수>(占位符为正数)的形式写入 /root/ttl/kept.txt。
  4. 以 1 秒的生存时间放入 cache:c,等待 2 秒,然后把未访问状态下的 DBSIZE 与访问之后的 DBSIZE,以 before=<n> after=<n> 的形式写入 /root/ttl/lazy.txt。
  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 的陷阱

以 60 秒的生存时间放入 cache:b 之后,用 SET cache:b <새값>(占位符为新值)只更新值。把 TTL 变成 -1 的情况记录到 /root/ttl/lost.txt,再把用 KEEPTTL 重试的结果,以 ttl=<양수>(占位符为正数)的形式写入 /root/ttl/kept.txt。

明明只更新了值,生存时间却消失了。有一个选项可以保持生存时间。

观察过期并不会立即归还内存

以 1 秒的生存时间放入 cache:c,等待 2 秒,然后把未访问状态下的 DBSIZE 与访问之后的 DBSIZE,以 before=<n> after=<n> 的形式写入 /root/ttl/lazy.txt。

过期时间已过、但没有人访问的键,会在一段时间内继续留着。对比一下查询前后的数量。

设置驱逐策略

把 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 的键。它必须是能在生产环境中定期运行的形式。