应首先监控evicted_keys是否持续增长,因其是淘汰行为发生的直接证据;再结合used_memory_dataset与maxmemory比值、mem_fragmentation_ratio及maxmemory-policy配置,综合判断淘汰真实性与合理性。

看 evicted_keys 是否真在增长,而不是只查大Key
Redis 的淘汰行为是否真实发生,第一眼必须盯住 evicted_keys。它记录了自启动以来被内存策略主动驱逐的 key 总数,且是单调递增的——只要这个值每分钟都在涨,就说明淘汰正在持续发生。
执行:redis-cli info stats | grep evicted_keys
如果返回类似 evicted_keys:124890 且多次执行后数值明显上升(比如 30 秒内 +500),那问题已确认存在。此时别急着跑 --bigkeys,因为:
-
--bigkeys只统计逻辑长度(如STRLEN),和实际内存占用无关 - 一个
user:session:abc字符串可能只有 1KB,但因内部编码升级、SDS 头开销、指针结构膨胀,真实占内存 4MB ——--bigkeys完全看不到 - 频繁淘汰更常由“一堆中等 size + 高频写入”的 key 共同导致,而非单个显眼大 Key
用 MEMORY USAGE + SCAN 精准抓出高内存+高访问的候选Key
真正该扫的是:哪些 key 占内存多、又正在被频繁写入?这需要组合两个命令:
先用 SCAN 拉出一批疑似业务前缀的 key(比如 cache:、session:、user:):redis-cli --scan --pattern "cache:*" | head -n 1000
再对这批 key 逐个查真实内存占用:redis-cli MEMORY USAGE cache:user:1001
注意几个实操要点:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 别用
KEYS—— 会阻塞主线程,生产环境禁用 -
SCAN默认只查db0,业务 key 若在db3,必须加-n 3 - 单次
MEMORY USAGE耗时不高,但批量调用仍建议加sleep 0.01防抖动 - 若发现某类 key(如
cache:report:*)平均MEMORY USAGE> 512KB 且写入 QPS 高,就是重点怀疑对象
结合 info memory 判断是不是内存碎片或阈值设置过紧
即使 evicted_keys 在涨,也不代表一定是业务 key 写太多。得排除两类底层干扰:
执行:redis-cli info memory | grep -E "(used_memory_dataset|maxmemory|mem_fragmentation_ratio)"
重点关注三项:
-
used_memory_dataset长期 > 85%maxmemory:说明阈值设得太紧,小波动就会触发淘汰 -
mem_fragmentation_ratio> 1.5:表示 jemalloc 分配器碎片严重,Redis 报告的内存使用量(used_memory)远高于实际数据集大小(used_memory_dataset),这时淘汰可能是假警报 -
maxmemory为 0 或未配置:意味着没启用淘汰,evicted_keys不该增长 —— 若真在涨,说明配置被 runtime 修改过(CONFIG SET maxmemory),需查操作记录
别忽略淘汰策略本身是否匹配业务语义
比如用了 volatile-lru,但业务里大量缓存根本没设 TTL;或者用了 allkeys-lfu,却有一批冷数据长期不访问但必须保留 —— 这些都会让淘汰行为看起来“莫名其妙”。
查当前策略:redis-cli config get maxmemory-policy
常见错配场景:
- 业务 key 全部带 TTL,但策略配成
allkeys-lru:浪费计算资源扫描无过期时间的 key - 缓存层混存 session(需 TTL)和配置(永不过期),却配
volatile-ttl:配置类 key 永远不会被淘汰,但 session 可能被误杀 - 用
volatile-random应对突发流量:完全不看访问模式,容易误删热点 key
真正难定位的,往往不是“哪个 key 被删了”,而是“为什么这个策略在这个时刻选中了它”——这需要把 MEMORY USAGE、访问频次、TTL 剩余时间、策略算法逻辑(LRU 时间戳 / LFU 计数器衰减)四者叠在一起看。单靠一个指标,永远只能猜。










