
Redis 过期策略决定了带时效的键什么时候真正从内存消失。Redis 用「惰性删除 + 定期删除」两种机制配合清理过期键,再靠内存淘汰兜底,避免内存被死键撑爆。本文基于 Redis 7 验证,把定时、惰性、定期三种删除方式讲清楚,并说明 TTL 设置与内存淘汰的触发条件。看完你能解释「为什么键过期了内存还没降」,也会避开几个最常见的缓存误区。今天这篇文章,编程狮就把这块讲透。理解 Redis 过期策略的底层取舍,能帮你在上线前就把内存曲线算清楚,而不是等告警才手忙脚乱地排查。
先看结论
| 机制 | 触发时机 | 优点 | 代价 |
|---|---|---|---|
| 定时删除 | 到期立刻删 | 内存最及时 | CPU 压力大,Redis 不用 |
| 惰性删除 | 被访问时才删 | 零额外 CPU | 不访问就一直占内存 |
| 定期删除 | 周期性抽样删 | 折中方案 | 有概率清不干净 |
一句话:Redis 实际只用惰性删除加定期删除,内存淘汰是最后兜底。
一、先弄清楚:过期键为什么会占着内存
你给一个键设了 30 秒过期,到点后它不会立刻消失,内存也不一定马上降。这不是 Bug,而是 Redis 故意用「惰性 + 定期」组合换 CPU 性能。先读 Redis 教程 建立键与过期的基础,再看机制更顺。
1.1 TTL 是什么
TTL 过期时间就是键的存活倒计时。用 EXPIRE 设置秒数后,键到点变为逻辑过期,但物理删除要看下面的删除机制。
1.2 为什么要三种删除配合
单纯定时删除 CPU 吃不消,单纯惰性删除内存回收慢。Redis 选择惰性删除兜底正确性、定期删除做常规清扫,再用内存淘汰防止极端堆积。
二、惰性删除与 TTL 查询
惰性删除的逻辑很简单:键被访问时才检查是否过期,过期就当场删除并返回空。它零额外 CPU,但代价是「没人访问的过期键会一直占着内存」。
# 设置 30 秒过期
SET code:login:1001 "a1b2c3"
EXPIRE code:login:1001 30
# 查看还剩多少秒,-2 表示已过期被删
TTL code:login:1001
TTL 过期时间到达后,如果一直不访问,这个键就静默躺在内存里。更多命令细节见 Redis 详解教程。

三、定期删除:周期性抽样清理
定期删除由 Redis 后台定时执行:每隔一段时间随机抽一批带过期时间的键,删掉其中已过的,如果过期比例高就再抽一轮。它是对惰性删除的补漏,避免过期键永远不被访问。
# 相关配置(redis.conf 倾向性示意,非必须手改)
# hz 控制每秒定期删除的触发频率,默认 10
hz 10
# 单轮抽样上限
# ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 默认 20
定期删除不是全量扫描,所以「抽到的才清、没抽到的等下轮」,这也是过期键偶尔残留的原因。它和惰性删除配合,既控 CPU 又保内存。
四、内存淘汰与常见误区
当定期删除赶不上写入速度、内存逼近上限时,Redis 启用内存淘汰:按 maxmemory-policy 决定哪些键先走。常见策略有 noeviction(报错)、allkeys-lru(全量最近最少用)、volatile-ttl(优先淘汰快过期的)。
# 设置最大内存与淘汰策略(示例值)
CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lru
内存淘汰不等于过期删除,它是「内存满了」时的兜底,和 TTL 过期策略是两套机制,别混为一谈。
4.1 三个最容易踩的坑
| 现象 | 原因 | 修复 |
|---|---|---|
| 键过期了内存没降 | 靠惰性删除,未被访问 | 正常,定期删除会逐步回收,或主动访问触发 |
| 设了过期却还被读到旧值 | 从库同步延迟 / 主从不一致 | 读写分离场景以主库 TTL 为准 |
| 内存满后写入报错 | 用了 noeviction 又没淘汰 | 改 allkeys-lru 等策略 |

动手验证清单
按下面步骤在本机观察过期键的真实行为,把 Redis 过期策略的取舍看明白(命令基于 Redis 7,未在本机执行,请按你的版本核对输出):
- 前置安装:先装好 Redis 并启动服务,
redis-cli ping返回 PONG 表示就绪,确认连接正常再继续后面的命令,连不上先核对配置文件 bind 与端口。 - 运行设置:用
SET code:login:1001 "a1b2c3"写入再EXPIRE设 30 秒,预期TTL返回递减的秒数,到点后变 -2 表示键已被删,这是 TTL 过期时间最直观的验证。 - 配置与检查:用
CONFIG GET maxmemory-policy查看当前内存淘汰策略,检查 Redis 过期策略是否和你预期一致;调hz参数可以改变定期删除的触发频率。 - 验证惰性删除:键过期后不访问,用
INFO memory观察 used_memory 不会立刻下降;主动访问后才释放,这正是 Redis 过期策略用惰性删除换 CPU 的体现,也是「内存没降」现象的根因。 - 失败处理与排错:若内存满后写入报错,多半是默认 noeviction 所致,改成 allkeys-lru 即可;若过期键迟迟不回收,适当调高 hz 让定期删除更积极;若从库读到旧值,是以主库 TTL 为准的同步延迟。适用边界:纯缓存设 allkeys-lru,重要数据加 volatile-ttl,别让默认策略裸奔上线。
总结
Redis 过期策略由「惰性删除 + 定期删除」组合完成,定时删除只作理论对照。TTL 过期时间到点后键只是逻辑过期,物理删除发生在被访问时或定期抽样时;内存淘汰则是内存触顶时的独立兜底。
要点带走:
- 惰性删除保证正确性,定期删除做常规清扫,两者配合控 CPU 也保内存;
- 过期键偶尔残留是正常的,不是没生效;
- 内存淘汰与过期删除是两回事,上线必须设
maxmemory-policy。
下一步可结合业务设好最大内存与淘汰策略,再压测观察内存曲线。
延伸学习
这块知识系统补齐,按这个顺序来:
- 过期后怎么彻底释放,Redis 过期清除 给了实操视角;
- 断电后过期数据怎么办,Redis 持久化方案 讲了安全边界;
- 想搞懂它为什么快,Redis 缓存入门 补了加速原理。
常见问题
Q:键过期了为什么内存没立刻降?
A:因为 Redis 用惰性删除,过期键只有被访问时才真正删除,未被访问就暂时留在内存。定期删除会周期性抽样清理,所以通常会逐步回落,属于正常行为。
Q:内存淘汰和过期删除是一回事吗?
A:不是。过期删除处理「到点的键」,内存淘汰处理「内存满了先扔谁」。即使没有过期键,写入量大到触顶也会触发内存淘汰,二者机制独立。
Q:生产环境该用哪种淘汰策略?
A:缓存场景常用 allkeys-lru,让最久没用的键先走;若只想淘汰带过期的键,用 volatile-ttl。关键是必须显式设置,默认的 noeviction 会在内存满时直接拒绝写入。

TRAE-AI编程



