在 Redis 中,key 的自动删除 主要由两种核心机制触发:过期删除(针对设置了 TTL 的 key) 和 内存淘汰(针对内存超限时的 key) 。以下是具体场景、策略及原理的详细说明:
一、过期删除:Key 达到预设生存时间(TTL)后自动删除
Redis 支持为 key 设置过期时间(Time To Live, TTL) ,当 key 的存活时间超过 TTL 时,会被自动删除。这是最常见的"自动删除"场景。
1. 如何设置过期时间?
通过以下命令为 key 设置过期时间(单位:秒/毫秒):
EXPIRE key seconds:设置 key 在seconds秒后过期(如EXPIRE user:100 3600表示 1 小时后过期)。PEXPIRE key milliseconds:设置 key 在milliseconds毫秒后过期(如PEXPIRE session:abc 1800000表示 30 分钟后过期)。SET key value EX seconds:创建 key 时直接指定过期时间(如SET name "Alice" EX 60表示 60 秒后过期)。EXPIREAT key timestamp:设置 key 在某个 Unix 时间戳(秒)过期(如EXPIREAT order:2024 1717171200表示 2024-06-01 00:00:00 过期)。
2. 过期删除的触发策略(核心!)
Redis 并非实时扫描并删除所有过期 key(避免 CPU 资源浪费),而是通过 "惰性删除 + 定期删除" 结合的混合策略:
① 惰性删除(Lazy Expiration)
-
触发时机 :当客户端访问某个 key 时,Redis 会先检查该 key 是否已过期。
-
处理逻辑:
- 若 key 已过期:立即删除该 key,并返回
nil(表示 key 不存在); - 若 key 未过期:正常返回值。
- 若 key 已过期:立即删除该 key,并返回
-
优点:对 CPU 友好(仅在访问时检查),不影响其他操作;
-
缺点:若过期 key 长期不被访问,会一直占用内存("内存泄漏"风险)。
② 定期删除(Periodic Expiration)
-
触发时机 :Redis 每隔一段时间(默认 100ms ,可通过
hz配置调整,范围 1-500),主动随机抽取部分设置了过期时间的 key 进行检查。 -
处理逻辑:
- 从设置了过期时间的 key 中随机选取 20 个 (默认值,可通过
active-expire-effort调整)进行检查; - 删除其中已过期的 key;
- 若本轮检查中,超过 25% 的 key 已过期(说明过期 key 较多),则重复上述步骤(最多循环 10 次,避免阻塞主线程)。
- 从设置了过期时间的 key 中随机选取 20 个 (默认值,可通过
-
优点:主动释放部分过期 key 内存,弥补惰性删除的不足;
-
缺点:删除频率和影响范围可控(避免 CPU 占用过高)。
3. 过期删除的注意事项
- 过期精度:Redis 的过期时间是"近似精确"的(误差通常在毫秒级),受定期删除的频率影响,极端情况下可能延迟几秒删除。
- 永不过期的 key :若未设置 TTL(或 TTL 为
-1),key 不会自动删除(除非被内存淘汰)。 - 取消过期时间 :通过
PERSIST key命令可移除 key 的过期时间,使其永久有效。
二、内存淘汰:内存使用达到上限时自动删除 Key
当 Redis 的内存使用量达到 maxmemory配置的上限时(默认无限制,需手动配置),会触发 内存淘汰机制,根据预设策略自动删除部分 key 以释放内存。
**1. 核心配置:maxmemory与 maxmemory-policy**
maxmemory <bytes>:设置 Redis 最大可用内存(如maxmemory 4gb表示最大使用 4GB 内存)。maxmemory-policy <policy>:设置内存淘汰策略(决定删除哪些 key),默认策略为noeviction(不淘汰,直接返回错误)。
2. 内存淘汰策略(7 种可选)
根据 key 是否设置过期时间,分为两类策略:
① 针对"已设置过期时间的 key"的策略
volatile-lru(默认推荐):从已设置过期时间的 key 中,删除最近最少使用(LRU) 的 key。volatile-lfu:从已设置过期时间的 key 中,删除最近最不频繁使用(LFU) 的 key(Redis 4.0+ 支持)。volatile-ttl:从已设置过期时间的 key 中,删除剩余 TTL 最短 的 key(即将过期的优先删)。volatile-random:从已设置过期时间的 key 中,随机删除 一个 key。
② 针对"所有 key"的策略
allkeys-lru:从所有 key 中,删除最近最少使用(LRU)的 key(适合缓存场景,保留热点数据)。allkeys-lfu:从所有 key 中,删除最近最不频繁使用(LFU)的 key(Redis 4.0+ 支持)。allkeys-random:从所有 key 中,随机删除一个 key。
③ 不淘汰策略
noeviction:内存超限时,不删除 key,直接返回OOM command not allowed when used memory > 'maxmemory'错误(默认策略,需谨慎使用)。
3. 内存淘汰的触发流程
- 当 Redis 执行写操作(如
SET、LPUSH)时,检查内存使用是否超过maxmemory; - 若超过,根据
maxmemory-policy选择待删除的 key; - 删除 key 后,若内存仍超限,重复步骤 2(直到内存足够或触发
noeviction错误)。
4. 内存淘汰的注意事项
- LRU/LFU 近似算法 :Redis 并未实现严格的 LRU/LFU(避免遍历所有 key 耗时),而是通过随机采样 (默认 5 个 key,可通过
maxmemory-samples调整)估算最近使用情况,平衡精度与性能。 - 持久化影响:内存淘汰仅删除内存中的 key,若 key 已持久化到 RDB/AOF 文件,重启后仍会加载(需结合持久化策略)。
三、其他自动删除场景(罕见)
**1. 主动触发 FLUSHDB/FLUSHALL**
FLUSHDB:删除当前数据库的所有 key(需谨慎,不可逆);FLUSHALL:删除所有数据库的 key。 这两个命令是手动触发的"批量删除",不属于"自动删除",但可能被误配置为定时任务(如 cron 脚本)导致 key 被自动清除。
2. 集群模式下 Slot 迁移
在 Redis Cluster 中,当槽位(Slot)从一个节点迁移到另一个节点时,源节点会自动删除已迁移的 key(目标节点会新增 key)。这属于集群内部的自动数据同步,非用户感知的"删除"。
总结:Redis 自动删除 Key 的核心场景
| 触发类型 | 核心条件 | 策略/机制 | 典型场景 |
|---|---|---|---|
| 过期删除 | Key 的 TTL 到期 | 惰性删除(访问时检查)+ 定期删除(随机抽查) | 验证码(5 分钟过期)、会话 Token(30 分钟过期) |
| 内存淘汰 | 内存使用达到 maxmemory上限 |
按 maxmemory-policy删除(LRU/LFU/TTL/随机) |
缓存服务器内存不足时,删除冷数据释放空间 |
配置建议
- 过期删除:根据业务需求合理设置 TTL(如缓存数据设短期 TTL,永久数据不设 TTL);
- 内存淘汰 :缓存场景推荐
allkeys-lru(保留热点数据),持久化数据场景推荐volatile-lru(仅删除临时数据); - 监控 :通过
INFO stats命令查看expired_keys(过期删除的 key 总数)和evicted_keys(内存淘汰的 key 总数),评估自动删除效果。
通过这两种机制,Redis 实现了"自动管理 key 生命周期"的能力,既保证了内存效率,又避免了手动维护的繁琐。