Redis淘汰策略生效前提为maxmemory必须显式设为非零值,否则无论策略如何设置均不触发淘汰;volatile-lru在无过期key时退化为noeviction导致写失败,allkeys-lru更适配缓存场景;maxmemory-samples默认5已足够,调高增CPU开销;volatile-ttl易引发雪崩,应避免批量相同TTL。

maxmemory 必须先设,否则淘汰策略不生效
Redis 的淘汰策略(maxmemory-policy)只在 maxmemory 明确设为非零值后才起作用。默认 maxmemory 是 0(即无限制),此时无论你把 maxmemory-policy 设成什么,都不会触发淘汰——哪怕内存爆了也只会 OOM 报错或直接 crash。
实操建议:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 线上环境务必在
redis.conf中显式配置maxmemory,例如maxmemory 2gb;运行时也可用config set maxmemory 2gb,但重启后失效 - 不要依赖“默认够用”:容器或云实例的内存上限 ≠ Redis 自身内存上限,必须由 Redis 主动感知并控制
- 设值建议略低于宿主机可用内存(比如留出 10%),避免因 Redis 自身开销(如连接缓冲、AOF rewrite)导致系统级 OOM
volatile-lru 和 allkeys-lru 的核心区别不是“有没有过期时间”,而是“能不能保命”
很多人误以为 volatile-lru 更安全,因为只淘汰带 expire 的 key。但真实风险在于:如果当前所有 key 都没设过期时间,volatile-lru 就退化成 noeviction ——写操作全部失败,报 OOM command not allowed。
而 allkeys-lru 始终有 fallback 能力,只要存在访问历史,就能淘汰。
实操建议:
- 缓存场景(如用户 session、热点商品)优先选
allkeys-lru:你无法保证所有 key 都打了expire,漏设一个就可能全链路写失败 - 仅当业务明确分层(例如:一部分 key 必须永驻,另一部分全是临时缓存且必设 TTL)时,才考虑
volatile-lru - 用
info keyspace定期检查各 DB 中expires字段占比,若长期expires=0,volatile-*策略等于摆设
maxmemory-samples 决定 LRU 的“准度”,但调太高反而拖慢性能
Redis 的 LRU 不是精确排序,而是采样估算:maxmemory-samples 默认为 5,表示每次淘汰前随机抽查 5 个 key,挑其中 lru 值最小的淘汰。增大它能让淘汰更接近理论 LRU,但代价是 CPU 时间线性增长。
实操建议:
- 默认值 5 对大多数场景足够,除非你观察到冷数据残留严重(用
memory doctor或redis-cli --bigkeys辅助判断) - 调高时建议阶梯测试:先试
10,再20,同时监控evicted_keys和used_cpu_sys指标变化 - 超过
50基本没有收益提升,反而在高并发下明显增加延迟毛刺
volatile-ttl 看似合理,但极易引发雪崩式淘汰
volatile-ttl 淘汰剩余 TTL 最短的 key,逻辑清晰,但隐患在于:它鼓励“集中过期”。一旦批量写入的 key 设置了相同 TTL(比如统一设 3600 秒),它们会在同一秒内集体进入待淘汰队列,Redis 可能在单次淘汰周期里狂删数百 key,造成瞬时 QPS 波动和客户端超时。
实操建议:
- 绝对避免给大批量 key 设置完全相同的 TTL;如需定时清理,改用 staggered TTL(例如
expire key (3600 + random(300))) - 若必须用
volatile-ttl,配合maxmemory-samples调低(如设为 3),减小单次扫描压力 - 监控
expired_keys和evicted_keys的比值:若前者远高于后者,说明过期机制已在兜底,淘汰策略实际没怎么干活
mem_used_human、evicted_keys、rejected_connections 这三个指标,比死记八种策略名称有用得多。

















