不会主动丢数据,但内存超限时淘汰逻辑立即变为LFU,新写入低频key可能比久存冷key更早被淘汰;LFU初始化counter非零且带随机偏移,惰性填充计数器,高峰期切换易引发多轮非预期驱逐。

Redis 6.0+ 切换 maxmemory-policy 从 allkeys-lru 到 allkeys-lfu 会丢数据吗?
不会主动丢数据,但内存超限时的淘汰行为逻辑会立刻改变——新策略下,刚写入但访问频次低的 key 可能比“冷但存在久”的 key 更早被淘汰。
LFU 启动后,Redis 会为每个 key 初始化一个初始频次(counter),默认不是 0,而是带随机衰减偏移(避免新 key 一上来就被秒杀)。这个初始化过程不触发淘汰,但后续内存压力到来时,淘汰决策就完全按 LFU 分数走了。
-
lfu-log-factor和lfu-decay-time会影响频次衰减速度,不调的话默认值(10 和 1)在高吞吐场景下容易让热点 key 的计数“涨不动”或“掉太快” - 切换前后,
INFO memory中的evicted_keys会继续累加,但统计依据已切换,不能跨策略对比“淘汰效率” - 如果原 LRU 策略下已逼近
maxmemory,切 LFU 后首次触发淘汰时可能集中清掉一批低频 key,造成短时缓存命中率跳变
为什么必须在业务低峰期 reload 配置?
不是因为配置热加载本身卡顿,而是 LFU 的频次计数字典(lfu_counter 字段)需要在内存中为所有 key 补全——这个过程发生在第一次执行 MEMORY PURGE 或下一个定时淘汰周期开始前,是惰性填充的,但会增加单次命令响应延迟抖动。
- Redis 不会在
CONFIG SET时立即扫描全部 key 填充计数器,而是在访问 key 时顺手初始化;但淘汰逻辑启动后,未初始化的 key 默认计数取最小值,极易被误杀 - 高峰期大量 key 首次参与 LFU 淘汰计算,可能引发多轮非预期驱逐,尤其当
lfu-log-factor设置过小(如 1)时,不同访问频次的 key 计数区分度极低 - 用
redis-cli --scan | xargs redis-cli touch强制预热所有 key 的 LFU 计数器?别试——touch不触发 LFU 初始化,且全量 scan 在大实例上本身就会打满 CPU
CONFIG SET maxmemory-policy allkeys-lfu 后,哪些 key 会被优先淘汰?
不是“访问次数最少”的 key,而是“LFU 分数最低”的 key。这个分数由原始频次经对数缩放 + 衰减时间校准得出,公式是:score = log(factor * counter) + age_in_minutes / decay_time。
- 刚写入的 key:
counter初始为 5~10(取决于lfu-log-factor),但age_in_minutes为 0,分数偏低 → 容易被删 - 高频老 key:即使
counter没增长,只要没被衰减掉,分数仍高;但如果lfu-decay-time设成 0(禁用衰减),计数只增不减,最终退化成纯访问次数排序 - 用
OBJECT FREQ查看某个 key 当前 LFU 分数时,注意它返回的是原始 counter 值(0–255),不是最终淘汰用的 score
如何验证 LFU 策略已生效且行为符合预期?
别只看 CONFIG GET maxmemory-policy 返回 allkeys-lfu 就算完——得确认淘汰动作真按 LFU 逻辑走,且频次统计没被异常重置。
- 先设
lfu-log-factor 10和lfu-decay-time 1(默认值),用DEBUG HTSTATS 0观察 dict 中 key 的平均访问频次分布是否随压测逐渐分层 - 写入一批 key,用
OBJECT FREQ批量查初始 counter,再反复访问其中几个,隔几分钟再查——正常应看到被访问 key 的 counter 明显高于其他 - 触发一次人工淘汰(
CONFIG SET maxmemory 1再立刻设回原值),然后查INFO stats中的evicted_keys增量,并比对被删 key 的OBJECT FREQ值是否显著偏低
LFU 的核心复杂点不在开关本身,而在频次统计的惰性初始化、衰减时机与淘汰触发之间的竞态——这些细节不暴露在日志里,只能靠 OBJECT FREQ 和压测节奏交叉验证。

















