maxmemory是内存淘汰策略生效的前提,因其为0时redis不检查内存超限,所有策略均失效;volatile-ttl淘汰即将过期的key,volatile-lru淘汰最久未访问的过期key;allkeys-random和volatile-random因不可预测易致缓存雪崩,仅适用于压测或临时数据场景。

Redis内存淘汰策略不是“选一个就行”,而是必须配合 maxmemory 才生效;没设 maxmemory,所有淘汰策略都等于摆设。
为什么 maxmemory 是前提条件?
Redis 默认不限制内存使用(maxmemory 为 0),此时无论你配置 maxmemory-policy allkeys-lru 还是别的,都不会触发淘汰——因为 Redis 根本不检查内存是否超限。
常见错误现象:
- 明明配了
volatile-lru,但内存持续上涨、OOM 报错仍出现 -
INFO memory显示used_memory_human已超 10GB,maxmemory_human却显示0B
所以第一步永远是:先设 maxmemory,再选策略。生产环境建议值通常为物理内存的 75%~85%,留出空间给系统、fork、客户端缓冲等。
volatile-ttl 和 volatile-lru 的本质区别在哪?
两者都只作用于设置了过期时间(EXPIRE / SET ... EX)的 key,但淘汰逻辑完全不同:
-
volatile-ttl:每次淘汰时,扫描一批带过期时间的 key,挑TTL最小的那个删(即“马上就要过期”的) -
volatile-lru:维护一个近似 LRU 队列,只对带过期时间的 key 做访问时间排序,淘汰“最久没被访问过”的
使用场景差异明显:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 做会话缓存(
session:xxx均设 TTL=30m)、验证码(verify:123TTL=5m)——优先用volatile-ttl,避免把刚写入但还没用过的 key 淘汰掉 - 做通用缓存(如
user:1001、post:2048),且有明确热点——volatile-lru更合理,保留高频访问项
注意:volatile-ttl 不保证“绝对最短 TTL”,因为 Redis 采用采样机制,不是全量扫描。
为什么生产环境慎用 allkeys-random 和 volatile-random?
随机淘汰看似简单,但在真实业务中容易引发雪崩式命中率下跌:
- 缓存穿透风险放大:随机删掉一个本该长期存在的热点 key(比如全局配置
config:app),后续大量请求直接打穿到 DB - 无法预测行为:运维查问题时,无法从日志或监控推断“为什么这个 key 被删了”,排查成本陡增
- 和
noeviction一样,它不解决数据热度问题,只是把压力转嫁给下游
唯一适合的场景是:临时测试、压测环境,或极低价值、纯临时性的 key(如批量任务中间状态),且业务能容忍丢失。
allkeys-lfu 在什么情况下比 allkeys-lru 更稳?
LFU(Least Frequently Used)关注访问频次,LRU 关注最近访问时间。当业务存在“冷热分明 + 长期稳定热点”时,allkeys-lfu 更可靠:
- 例如商品详情页缓存:首页 banner 图片 key 每秒被读千次,但某促销活动页 key 只在开抢瞬间爆发访问,之后归于沉寂 —— LRU 可能把它保在内存里,LFU 会更快识别其低频本质
- LFU 有衰减机制(默认每分钟将计数右移 1 位),避免历史高频干扰当前决策
- 但 LFU 内存开销略高(每个
robj多存一个访问频次字段),且初始化阶段需积累访问样本,刚启动时效果不如 LRU 稳定
如果你的监控能看到 evicted_keys 持续上升,同时 keyspace_hits / keyspace_misses 比例恶化,不妨切到 allkeys-lfu 观察 24 小时。
真正难的是权衡:volatile-* 类策略要求你严格管控 key 的生命周期,而 allkeys-* 类策略则要求你接受无过期时间 key 也被淘汰的风险。没有银弹,只有根据 key 的语义、TTL 设置习惯、下游容错能力,去反复验证和微调。










