键与过期
对应官方文档:How Redis expires keys 与 Scanning keys
键空间(keyspace)是所有键的总称。本页学习如何安全地遍历键、删除键,以及 Redis 最有特色的过期机制——它是缓存、会话等场景的核心。
前置条件
请先完成数据类型中的示例,确保 task:t001、queue:tasks 等键已存在。下面的命令都在 redis-cli 中执行。
检查与重命名
EXISTS task:t001
TYPE task:t001
RENAME task:t001 task:t101
EXISTS task:t001
EXISTS task:t101你应该看到:
(integer) 1
hash
OK
(integer) 0
(integer) 1EXISTS 返回 1 表示键存在、0 表示不存在;RENAME 是原子操作,重命名后旧键立即消失。
删除键:DEL 与 UNLINK
DEL task:t101你应该看到:
(integer) 1DEL 同步删除并阻塞其他命令,键越大耗时越长。UNLINK 先从键空间摘除键,实际内存释放在后台异步完成,是删除大键时的推荐选择:
UNLINK task:t101设置过期时间
用 EXPIRE 为键设置 TTL(Time To Live,剩余存活秒数):
SET session:u001 "active"
EXPIRE session:u001 60
TTL session:u001你应该看到:
OK
(integer) 1
(integer) 59TTL 的返回值有三种含义:正数是剩余秒数;-1 表示键存在但没有过期时间;-2 表示键不存在。
过期时间也可以在写入时一步完成,验证码这类「限时一次性数据」通常这样写:
SET captcha:u001 "824193" EX 300
TTL captcha:u001你应该看到:
OK
(integer) 300还可以用 PERSIST 移除过期时间,让键变成永久键:
PERSIST session:u001
TTL session:u001你应该看到:
(integer) 1
(integer) -1💡 新手提示:对同一个键再次执行
SET会清除它的 TTL。想「更新值但保留过期时间」时,应使用SET key value KEEPTTL或继续用EXPIRE补设。
Redis 通过惰性删除(访问时检查)加定期抽样删除来清理过期键,所以过期键可能在 TTL 归零后的一小段时间内仍占用内存,这是正常现象。
遍历键:SCAN 而不是 KEYS
KEYS pattern 会一次性扫描全库并阻塞 Redis,键多时可能造成线上卡顿,生产环境应避免使用。SCAN 用游标分批遍历,每次只处理少量键:
SCAN 0 MATCH task:* COUNT 100你应该看到类似输出(游标值取决于实际数据):
1) "0"
2) 1) "task:t001:tags"
2) "task:t001"返回的第一行是下一次迭代的游标,0 表示遍历结束。在 redis-cli 中可以直接用 --scan 参数自动循环:
docker exec -it redis-tutorial redis-cli --scan --pattern "task:*"你应该看到:
task:t001:tags
task:t001键命名建议
- 用冒号分层,如
task:t001:tags,便于按前缀管理和扫描。 - 把对象类型放进键名,如
session:u001、stats:views,读命令时一目了然。 - 避免超长键名:键本身也占内存,长键名应在不损失可读性的前提下缩短。
小结
EXISTS、TYPE、RENAME用于检查和整理键;删除大键优先用UNLINK。EXPIRE/SET ... EX设置 TTL,TTL返回剩余秒数或-1/-2状态码,PERSIST取消过期。- 重新
SET会清除 TTL,需要保留时使用KEEPTTL。 - 线上遍历键使用
SCAN或redis-cli --scan,不要用会阻塞的KEYS。
练习
- 写入
cache:home并设置 120 秒过期,然后用TTL观察数值递减,等它过期后再GET并解释(nil)。 - 对
cache:home重新SET一次值,检查TTL是否变成-1,再用KEEPTTL验证保留过期时间的写法。 - 使用
--scan列出所有以queue:开头的键。
下一步:进入管道与事务,学习批量执行命令与原子性保证。