过期与内存淘汰
用途:解释“内存打满”“缓存命中率突然下降”,并正确配置淘汰策略
过期删除机制
「过期删除机制」小节链接Redis 采用两种组合:
- 惰性删除:访问 key 时才判断是否过期,过期则删除。CPU 友好,但未被访问的过期 key 长期占内存。
- 定期删除:后台周期任务随机抽样若干带 TTL 的 key,删除其中已过期的;若过期比例超阈值则重复。
含义:过期不等于立即释放内存。大量 key 同时到期会造成 CPU 尖峰与延迟毛刺,因此 TTL 要打散。
淘汰策略(maxmemory-policy)
「淘汰策略(maxmemory-policy)」小节链接| 策略 | 行为 | 适用 |
|---|---|---|
noeviction |
写命令报错(默认) | 不允许丢数据的场景,需容量告警 |
allkeys-lru / allkeys-lfu |
全体 key 中按最近使用/频率淘汰 | 通用缓存 |
volatile-lru / volatile-lfu |
只在带 TTL 的 key 中淘汰 | 混合用途实例(部分数据希望常驻) |
allkeys-random / volatile-random |
随机淘汰 | 访问均匀的场景 |
volatile-ttl |
优先淘汰剩余 TTL 最短的 | 想让短生命周期数据先走 |
注意:volatile-* 在没有可淘汰 key 时行为退化为报错。
LRU/LFU 的实现细节
「LRU/LFU 的实现细节」小节链接Redis 不做精确 LRU,而是近似 LRU:每个对象记录 lru 时钟,淘汰时随机采样 maxmemory-samples(默认 5)个 key 比较,取最久未用者。采样数越大越接近 LRU,CPU 成本越高。
lfu-log-factor 与 lfu-decay-time 控制频率计数(对数递增 + 衰减),适合访问分布长尾的缓存。
内存治理动作
「内存治理动作」小节链接- 设
maxmemory为实例可用内存的合理比例(留 fork 与缓冲余量)。 - 监控
evicted_keys、expired_keys、used_memoryvsmaxmemory、碎片率;淘汰发生意味着命中率下降,要告警。 - 大 key 扫描(
--bigkeys、MEMORY USAGE)与热 key 识别(--hotkeys、INFO commandstats、monitor 慎用)。 - 区分“缓存”与“存储”用途:混用会让淘汰策略互相伤害,最佳实践是拆实例。
- 给缓存类 key 一律设 TTL,并避免把无 TTL 的常驻数据塞满实例。
常见误区
「常见误区」小节链接| 误区 | 修正 |
|---|---|
| 内存满才发现没设 maxmemory | 未设时可能撑爆 OS 内存并被 OOMKill |
用 volatile-lru 但所有 key 都无 TTL |
无可淘汰对象,写直接失败 |
| 认为过期 key 会立刻释放 | 惰性 + 采样删除,内存下降有延迟 |
| 淘汰策略当容量方案 | 容量不足应扩容或清理,而不是靠淘汰兜底 |
| 大量 key 设同一 TTL | 集中过期造成抖动与雪崩 |
延伸阅读
「延伸阅读」小节链接- Redis 官方文档:Key expiration、LRU cache、Data eviction
- 《Redis 设计与实现》客户端与服务器部分