Redis默认采用noeviction策略,内存满时写操作报错而读正常,本质是“宁可失败也不丢数据”;需配maxmemory、避免误启volatile类策略、核心key不设EXPIRE、用OBJECT FREQ/IDLETIME验证、监控evicted_keys和rejected_connections。

用 noeviction 策略锁死淘汰行为
Redis 默认不淘汰数据,但很多人没意识到它其实是靠 noeviction 实现的——内存满后写操作直接报错,读照常。这不是“没配置就不管”,而是明确选择了“宁可失败也不丢数据”的底线逻辑。
实操建议:
- 确认当前策略:
CONFIG GET maxmemory-policy,输出必须是noeviction - 务必配
maxmemory,否则 Redis 会一路涨到系统 OOM;比如设为2gb:CONFIG SET maxmemory 2gb - 不能只靠这个策略兜底:它不解决内存增长问题,只是把风险暴露出来——你得同步做容量规划、监控告警、扩容预案
避免误启 volatile-* 类策略导致核心 key 被连带清除
只要给某个 key 设置了 EXPIRE,它就进了 volatile 淘汰池。哪怕你只对验证码、临时 token 这类数据加过期时间,一旦配置成 volatile-lru 或 volatile-ttl,而这些 key 又占了大头,Redis 就可能在压力下误清掉你本以为“安全”的核心缓存(比如用户登录态,你忘了它也有 EXPIRE)。
实操建议:
- 核心数据一律不设
EXPIRE—— 即使是 session,也用服务端续期 + 长 TTL,而非依赖 Redis 自动过期 - 检查所有写入路径:
SET、SETEX、EXPIRE命令调用点,确认有没有无意识混用 - 用
SCAN+TTL定期抽检:SCAN 0 MATCH "user:*" COUNT 1000后跟TTL,看是否出现非预期的过期时间
用 OBJECT FREQ 和 OBJECT IDLETIME 主动验证 LFU/LRU 影响范围
即使你选了 allkeys-lfu 或 allkeys-lru,Redis 的近似算法也不是完全不可控。某些核心 key 如果访问频次/时间间隔刚好落在采样盲区,仍可能被误判为冷数据。别等出事才查,得提前摸清它的“判断依据”。
实操建议:
-
OBJECT FREQ <key>查 LFU 频率计数器值(0–255),核心 key 应稳定在高位(如 >100) -
OBJECT IDLETIME <key>查 LRU 空闲秒数,高频核心 key 应远小于淘汰阈值(比如你设了 300 秒采样窗口,它却显示 280+,就得警惕) - 注意:这两个命令本身有性能开销,不要在大 key 上高频扫;建议只抽检 TOP 20 核心 key
监控 evicted_keys 和 rejected_connections 是唯一真实指标
配置写得再漂亮,不如看两个指标:如果 evicted_keys > 0,说明淘汰已发生,noeviction 失效;如果 rejected_connections 持续上升,说明写入被拒,业务可能已受损。日志里报错 (error) OOM command not allowed when used memory > 'maxmemory' 就是它在喊救命。
实操建议:
- 在 Prometheus + Grafana 中固定看这两项,阈值设为 0 报警(不是“大于 0”,而是“突增 > 0”)
- 不要只盯
used_memory:它可能离maxmemory还差 100MB,但碎片率高或子进程 fork 内存预留不足,照样触发拒绝 - 线上切策略前,先用
redis-cli --intrinsic-latency 100测延迟毛刺——有些策略(如 LFU 衰减)会在后台悄悄吃 CPU
真正难的不是选哪个策略,而是让所有写入方对 key 的生命周期达成共识:谁设过期、谁负责续期、谁承担丢失后果。配置只是最后一道闸,闸前的水位和流向,得靠代码和流程管住。

















