evicted_keys突增本身不直接引起网络抖动,而是淘汰动作阻塞主线程导致延迟尖峰;volatile-ttl策略下整数ttl集中到期触发脉冲式同步淘汰,引发cpu争用、命令处理骤降及周期性20–50ms延迟。

evicted_keys突增本身不直接引起网络抖动,而是淘汰动作阻塞主线程的副作用
Redis 的 evicted_keys 是个累计计数器,它上涨只是结果,真正造成延迟尖峰的是背后触发的同步淘汰逻辑。当策略为 volatile-ttl 或 allkeys-lru 时,Redis 在内存不足时必须在主线程中逐个释放 key —— 这个过程无法异步化,会抢占事件循环资源。
常见错误现象包括:
– redis-cli --latency 显示周期性 20–50ms 延迟尖峰
– 客户端偶发 READONLY You can't write against a read only replica(实际是写命令被卡住,非真实只读)
– INFO stats 中 total_commands_processed 短时骤降、expired_keys 同步飙升
volatile-ttl 策略下 TTL 集中到期是抖动主因
业务批量设置整数 TTL(如 60s、120s)会导致大量 key 在同一时间窗口进入 expires 字典末尾。Redis 每 100ms 主动扫描该字典,一旦发现高密度“临期 key”,就会集中触发惰性检查 + 主动驱逐,形成淘汰脉冲。
这种行为在短生命周期场景(如 session、临时 token)中尤为明显,表现为:
– evicted_keys 每秒突增数百甚至上千
– INFO memory 中 mem_fragmentation_ratio 剧烈波动(频繁 malloc/free)
– CPU 使用率对应出现尖峰,但不是因计算密集,而是因内存分配锁争用
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
为什么 allkeys-lfu 能缓解但不能直接替换 volatile-ttl
allkeys-lfu 不依赖时间戳,天然避开“整点过期”问题,但上线前必须做三件事:
– 把带 EXPIRE 的 key 改为永不过期,value 内嵌逻辑过期字段(如 {"exp": 1743790260, "data": "..."} )
– 显式配置 lfu-log-factor 10 和 lfu-decay-time 1,否则高频 key 计数器增长过慢,冷 key 长期滞留
– 接受每个 key 多占约 16bit 内存开销,压测确认内存增长在可接受范围
注意:LFU 计数器只在 key 被读取时更新;首次写入后若无访问,不会进入淘汰排序——这点常被忽略,导致误判“策略没生效”。
只设 maxmemory 不配 maxmemory-policy 是最隐蔽的抖动诱因
默认策略是 noeviction,意味着内存打满后所有写命令直接返回 (error) OOM command not allowed when used memory > 'maxmemory'。这不是“抖动”,是服务级中断,但监控上可能只看到 evicted_keys = 0 和大量客户端超时,容易误判为网络或客户端问题。
真正难处理的从来不是策略参数本身,而是业务语义和淘汰机制之间的错配:比如一个 key 该不该被淘汰,得由业务逻辑决定,而不是靠 Redis 自动猜。










