不能直接用redis-benchmark测淘汰策略,因其默认不设TTL,全写永不过期key,导致volatile-lru等策略退化为noeviction并报OOM;真实验证需分批写入30–300秒TTL的key使内存达85%阈值后持续注入,监控evicted_keys持续增长、used_memory_human逼近上限、expired_keys不显著高于evicted_keys。

为什么不能直接用 redis-benchmark 测淘汰策略
因为 redis-benchmark 默认不带 TTL,所有 key 都是永不过期的。你设了 volatile-lru,它却狂塞没过期时间的 key,策略直接退化成 noeviction,一写就报 (error) OOM command not allowed when used memory > 'maxmemory'——这不是策略失效,是测试方式把策略“绕过去了”。
必须分三步构造真实高压淘汰压力流
核心不是压并发数,而是让内存稳定卡在 maxmemory 的 85%–95%,同时确保淘汰器有“可选的冷 key”可删。
- 预热阶段:用脚本批量写入带 TTL 的 key(建议
SETEX key 60 "val",TTL 设 30–300 秒),直到used_memory_human达到maxmemory的 ~85% - 持续注入阶段:启用一个长运行脚本,每秒写入几百个新 key(同样带 TTL),并混入访问频次差异——比如 20% 的 key 每秒被
GET一次(热 key),其余只写不读(冷 key) - 验证阶段:不看内存是否回落,盯住
evicted_keys是否持续增长;若它长期为 0,说明根本没触发淘汰,要么内存没到阈值,要么策略配置被覆盖(CONFIG GET maxmemory-policy必须现场查)
监控时最常忽略的三个干扰信号
很多同学看到 used_memory_human 下降就以为淘汰起了作用,其实可能是自然过期在释放内存。真正能证明淘汰策略生效的只有三个指标联动:
-
evicted_keys上升 +expired_keys增速明显低于它 → 淘汰器真在干活 -
mem_fragmentation_ratio> 1.5 → 内存碎片严重,此时即使evicted_keys在涨,新写入仍可能失败,得先MEMORY PURGE或重启 -
used_memory_human稳定在maxmemory附近小幅波动(如 1.98G / 2G),而不是一路冲顶后崩掉 → 策略正在负反馈调节
脚本里最容易写错的 TTL 和 key 分布逻辑
很多人用 __rand_int__ 生成 key,但忘了加 TTL,或者 TTL 设成 1 秒——结果 key 还没进淘汰队列就被惰性删除干掉了,evicted_keys 一直为 0。真实模拟要守住两个边界:
- TTL 不能短于 Redis 的定期清理周期(默认 100ms 执行一次,每次最多检查 20 个库),建议最低设 30 秒,避免“刚写完就过期”,绕过淘汰器
- key 命名要有区分度:热 key 用固定前缀(如
hot:user:123),冷 key 用随机前缀(如cold:uuid4()),否则allkeys-lru可能把热 key 当冷 key 删了 - 别用单个
SET循环,改用PIPELINE批量提交,否则网络开销会掩盖淘汰行为本身
真实压测中,最难调的从来不是 QPS,而是让 Redis 内存像呼吸一样稳定起伏——这要求你对 maxmemory-policy、maxmemory-samples、key 访问模式三者关系有手感。参数写对只是起点,数据怎么喂进去,才是淘汰策略能不能扛住的关键。











