是的——如果一个 key 设置了过期时间,但它之后从未被访问,那么惰性删除不会主动删除它。
但 Redis 仍然会通过 定期删除机制(Active Expire Cycle) 逐步把它清掉,只是“不是立即,也不是严格覆盖全部”。
下面解释得更清晰。
🔍 1. 惰性删除(Lazy Expire)= 被访问时才删除
惰性删除完全依赖访问触发:
- GET key
- EXISTS key
- SET key
- HGET key.hfield
- DEL key
- 等等访问命令
只要你根本不访问这个 key,惰性删除永远不会触发。
👉 所以 “不访问 + 过期” 并不会触发删除。
🔍 2. 定期删除(Active Expire Cycle)= Redis 真的会主动清理,但不是 100% 覆盖
Redis(包括华为云分布式 Redis)会 每秒多次随机抽样部分 key 空间 来检查过期:
- 默认约扫描每个数据库中随机的若干个 TTL 桶
- 每次最多 25% 的过期 key 会被删掉
- 扫描时间有上限(避免阻塞)
👉 这意味着:
❗不访问的 key,如果过期了,不会立即删除,只会在定期周期被“随机”抽到时删除。
而当:
- TTL key 数量巨大时
- 某些 key 所在 bucket 长时间没被扫描到
就会出现:
key 明明过期了,但在 Redis 内存里还待着。
这就是你担心的“堆积”。
❗所以严格结论:
| 删除方式 | 该 key 是否会被删? | 什么时候删? |
|---|---|---|
| 惰性删除 | ❌ 不访问就不会删 | 永远不删 |
| 定期删除 | ✔ 可能清掉 | 看扫描是否扫到,不保证立即 |
📌 那最终会不会一直不被删?
不会。
Redis 定期删除是持续循环的,随着时间越久,最终会扫描到所有 TTL 桶。
但:
- 短时间确实可能堆积
- TTL 特别多的情况下,清理速度可能比生成速度慢
- 业务会误以为 key 没有被删除
- 内存曲线会上涨不下降
这些就是“堆积问题”的来源。
📚 进一步解释:为什么 Redis 不保证 100% 主动删除?
因为 Redis 单线程,不可能把大量时间花在清理过期 key 上,否则业务读写就延迟暴涨。
所以它有一个平衡机制:
- 惰性删除:高效,但只能删除被访问的
- 定期删除:主动,但扫描时间有上限
这就是过期机制的核心。
🧭 总结(最精准版本)
如果 key 过期后没有被访问:
- 惰性删除:永远不会删除
- 定期删除:迟早会删除,但不是立即,也不是严格保证按时删
如果 TTL key 量大,会出现:
- 过期 key 堆积
- 内存上升不下降
- AOF/RDB 变大
- 主从同步压力变大
