Java面试题学习4 - Redis的删除策略

一、定时删除

原理:为每个设置了过期时间的 key 创建一个定时器,到期时立即删除。

优点:内存友好,过期数据能被及时清理。

缺点:每个 key 都要维护一个定时器,当存在大量过期 key 时,定时器本身消耗大量 CPU 资源,影响服务性能。Redis 实际上未采用此策略。


二、惰性删除(Redis 默认启用)

原理:不主动删除,当客户端访问某个 key 时,Redis 先检查其是否过期,若已过期则删除并返回空。

优点:CPU 友好,只在访问时才做检查,不额外消耗计算资源。

缺点:冷数据(长期不被访问的 key)即使已过期也不会被删除,持续占用内存。


三、定期删除(Redis 默认启用)

原理:Redis 默认每 100ms 执行一次扫描,从设置了过期时间的 key 集合中随机抽取 20 个 进行检查,删除其中已过期的 key。若本次扫描中过期 key 的比例超过 25%,则立即进行下一轮扫描,直到比例降低或达到时间上限为止。

优点:兼顾了 CPU 和内存,是定时删除和惰性删除的折中方案。

缺点:随机抽样决定了无法保证所有过期 key 都被及时清理,存在漏删的可能。


四、惰性删除 + 定期删除(Redis 实际采用的策略)

Redis 同时开启惰性删除和定期删除,两者互补:定期删除负责周期性批量清理,惰性删除在访问时兜底检查。但两者都无法 100% 覆盖所有过期 key,仍可能有漏网之鱼长期占用内存。


五、内存淘汰策略(兜底机制)

当 Redis 内存使用达到 maxmemory 阈值时触发,这里需要纠正一点:内存淘汰并不只针对过期 key,而是根据配置的淘汰策略决定淘汰哪些 key。常见策略有以下几种:

策略 说明
noeviction 不淘汰,内存满后写操作直接报错(默认)
allkeys-lru 从所有 key 中淘汰最近最少使用的
volatile-lru 从设置了过期时间的 key 中淘汰最近最少使用的
allkeys-random 从所有 key 中随机淘汰
volatile-random 从设置了过期时间的 key 中随机淘汰
volatile-ttl 优先淘汰剩余存活时间最短的 key
allkeys-lfu 从所有 key 中淘汰访问频率最低的(Redis 4.0+)
volatile-lfu 从设置了过期时间的 key 中淘汰访问频率最低的(Redis 4.0+)

实际生产中最常用的是 allkeys-lru,适合缓存场景。


一句话总结:

Redis 用"惰性 + 定期"双策略处理过期 key,再用"内存淘汰"作为最后一道防线,三者共同保障内存安全。