🚀 1、简述
在使用 Redis 构建缓存系统时,很多开发者只设置了 EXPIRE
但却忽略了背后 Redis 的过期删除机制与内存淘汰策略。理解这两者非常关键,直接关系到你的缓存系统是否高效、稳定、可控。
本文将深入剖析 Redis 中的两类机制:
- ⏰ 过期删除策略:key 如何在过期后被清除?
- 🧹 内存淘汰策略:内存满了之后,哪些 key 会被删除?
2、⏰ Redis 的过期删除策略(Key Expiration)
Redis 支持给 key 设置 TTL(Time To Live),例如:
SET user:1:name "Tom" EX 60 # 设置60秒后过期
Redis 有三种过期删除策略:
策略名称 | 触发方式 | 特点与代价 |
---|---|---|
惰性删除 | 访问 key 时触发 | 延迟释放内存,资源占用低,但可能滞留 |
定期删除 | 每秒扫描过期 key | 有概率清理过期 key,减缓内存膨胀 |
主动删除 | 内存不足时触发 | 与内存淘汰策略结合,主动回收 |
🔍 Redis 实际如何执行过期?
Redis 并不会在 key 到期的一刻立刻删除它,而是:
- 每秒随机抽取一批 key 检查过期(默认每次检查 20 个)
- 被访问的 key 会“惰性检查”,若过期就顺便删掉
- 在内存压力大时,会加速触发清理
3、🧹 Redis 内存淘汰策略(Eviction Policy)
当 Redis 达到最大内存上限(由 maxmemory
指定)时,就必须开始淘汰旧数据。此时就轮到 内存淘汰策略 发挥作用。
Redis 提供的 8 种淘汰策略:
策略 | 描述 |
---|---|
noeviction | 默认策略,拒绝写入新数据,直接报错 |
allkeys-lru | 所有 key 中,淘汰最近最少使用的 |
volatile-lru | 只在设置了 TTL 的 key 中,淘汰最少使用的 |
allkeys-random | 所有 key 中,随机淘汰 |
volatile-random | 只在设置了 TTL 的 key 中,随机淘汰 |
volatile-ttl | 只淘汰 TTL 最短的 key(最早过期) |
volatile-lfu | 只在设置了 TTL 的 key 中,淘汰最少频率使用 |
allkeys-lfu | 所有 key 中,淘汰最少频率使用 |
🛠 配置示例:
maxmemory 512mb
maxmemory-policy allkeys-lru
4、🎯 实践场景与建议
✅ 场景 1:普通缓存场景(推荐)
maxmemory 1gb
maxmemory-policy allkeys-lru
- 优点:自动替换最不常访问的 key,效果最贴近缓存的预期行为
- 使用方式:
SET user:123 "json-data" EX 300
✅ 场景 2:数据较重要,只删除过期 key
maxmemory 1gb
maxmemory-policy volatile-lru
- 仅淘汰设置了过期时间的 key,持久 key 不被动清除
- 适合混合数据结构:部分缓存 + 部分持久值
✅ 场景 3:用户限流或验证码存储
SET captcha:uid123 "XYZ" EX 60
- 结合
volatile-ttl
策略,可以优先清理即将过期的验证码等
5、🧪 示例:模拟淘汰行为
# 配置
CONFIG SET maxmemory 100kb
CONFIG SET maxmemory-policy allkeys-lru
# 插入多个 key
for i in {1..100}; do
SET "key$i" "$(openssl rand -hex 20)"
done
# 查看哪些 key 被淘汰了
INFO stats | grep evicted
输出示例:
evicted_keys:57
说明有 57 个 key 被自动淘汰,Redis 按 LRU 策略生效。
🧠 附加建议
- ⚠️ Redis 淘汰的是“key”,不是“内存最占用的值”
- ✅ Redis 7.0+ 中 LFU 策略适合热点数据,尤其在流量分布极不均衡时更精准
- 🛠 若你使用 Redis 作为数据库(而非缓存),应避免使用淘汰策略,并开启持久化
6、📌 总结
分类 | 策略类型 | 控制方式 | 推荐场景 |
---|---|---|---|
过期删除策略 | 惰性/定期 | 自动 | 所有 Redis 使用 |
内存淘汰策略 | 8 种策略 | 配置项控制 | 缓存系统、高频数据 |
📚 推荐配置模板
# 设置最大内存限制
maxmemory 512mb
# 设置淘汰策略
maxmemory-policy allkeys-lru