994 字
约 3 分钟
7
S12-B03 · 过期、淘汰与内存

适用读者:线上遇到"内存打满 / key 莫名消失"的人。
前置:S12-B02。
实测环境:Redis 7.0.15(2026-11-05)。
覆盖旧文:874(82) 875(79) 568(4) 1577(122) = 287 点。
覆盖扩展:E-S12-004(惰性+定期删除)、E-S12-005(淘汰策略)。
上一篇:S12-B02 · 五种数据结构与底层编码
下一篇:S12-B04 · 持久化。


1. 一句话结论

过期(expire)和淘汰(eviction)是两件事:过期是"到点删",淘汰是"内存满了按策略删"。前者靠惰性+定期,后者只在 maxmemory 触发。


2. 实测:过期到底怎么生效

redis-cli set t1 v ex 2
redis-cli ttl t1          # → 2
sleep 2.2
redis-cli get t1          # → (nil)

过期删除的两种方式(E-S12-004):

方式 说明
惰性删除 访问时检查是否过期 → 过期就删
定期删除 每秒若干次随机抽查过期 key

后果:过期的 key 可能"还在内存里"(没人访问 + 没被抽查到)——这是"内存比预期高"的常见原因。


3. 实测:淘汰策略真的会删

redis-cli config set maxmemory 5mb
redis-cli config set maxmemory-policy allkeys-lru
# 写入 2 万个 200 字节的 value

实测输出:

写入 2 万个大 value 后:evicted_keys 177281 → 207084(新增淘汰 29803 个)
used_memory_human:5.00M
maxmemory_human:5.00M

两个关键观察:

观察 结论
淘汰了 29,803 个 key 内存满时按策略删
used_memory 恰好 5.00M 不会超限(超限前就淘汰)

4. 八种淘汰策略(E-S12-005)

策略 范围 说明
noeviction(默认) — 内存满时写入报错
allkeys-lru 所有 key 最近最少使用
allkeys-lfu 所有 key 最不经常使用(4.0+)
allkeys-random 所有 key 随机
volatile-lru 仅设了过期时间的 LRU
volatile-lfu 仅过期 LFU
volatile-random 仅过期 随机
volatile-ttl 仅过期 剩余 TTL 短的先删

判据:

缓存场景(数据可重建)→ allkeys-lru / allkeys-lfu
混合存储(部分不可丢)→ volatile-*
不确定 → 先保持 noeviction(会报错而不是静默丢数据)

"为什么默认是 noeviction":宁可报错也不要静默丢数据——这是安全默认值。


5. LRU 与 LFU 的差别(A-1577)

LRU LFU
依据 最近访问时间 访问频率(带衰减)
适合 有明显热点的场景 长期热点(防"偶发访问挤掉热 key")
缺点 一次全表扫描会挤掉热点 需要时间累积

"缓存污染":一次 KEYS/批量任务会把热点挤出 LRU —— LFU 或 allkeys-lfu 更抗污染。


6. 五个误区

误区 真相
"设了过期就一定立刻释放" 惰性+定期,可能延迟
"默认会淘汰" 默认 noeviction(报错)
"淘汰会保证不丢数据" 缓存场景可丢,存储场景要选对策略
"LRU 一定比 LFU 好" 抗缓存污染 LFU 更强
"内存满只是变慢" noeviction 下写入直接失败

7. 自检

  1. 过期删除的两种机制?为什么过期 key 可能还占内存?
  2. 实测淘汰了多少个?内存为什么停在 5.00M?
  3. 八种淘汰策略大致怎么分组?
  4. 默认策略是什么?为什么这样设计?
  5. LRU 与 LFU 的适用差异?

8. 下一篇

S12-B04 · 持久化:RDB / AOF / 混合

内存讲完,下一篇讲"宕机会丢多少":三种持久化方式的差异与选择。


本篇属于系列《S12 · Redis 与缓存》。旧文来源:A-874/875/568/1577;扩展点 E-S12-004/005。过期与淘汰数据为 Redis 7.0.15 实测。

S12-B03 · 过期、淘汰与内存
https://www.clxhxhhr.top/posts/5347/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。