不能只配allkeys-lfu,必须同步预估峰值内存、调优lfu-log-factor与lfu-decay-time、配合业务层逻辑过期;因LFU非自动防爆阀,突发流量下易OOM,短生命周期Key无TTL会导致volatile-lfu失效,且allkeys-lfu内存开销高15%。

直接结论:不能只配 allkeys-lfu 就完事,必须同步做三件事——精准预估峰值内存、启用 lfu-log-factor 和 lfu-decay-time、配合业务层逻辑过期控制冷热节奏。
为什么 allkeys-lfu 单独上不能扛住突发流量
LFU 不是“自动防爆阀”,它只是让淘汰更合理。突发流量下如果没预热、没限 Key 范围、没调参,照样会 OOM:
- 默认
lfu-log-factor=10在秒级激增访问下,计数器涨得太快,刚热起来的爆款可能被误判为“高频但非长期热点”,反而挤占内存 - 若大量 Key 是短生命周期(如 60s session),但没设 TTL,
volatile-lfu直接失效,退化成noeviction,写入直接报错 -
allkeys-lfu比allkeys-lru多存一个 16bit 计数器,内存开销高约 15%,压测时若忽略这点,上线后碎片率可能突然冲到 1.8+
动态扩容 maxmemory 的实操边界在哪
扩容不是拍脑袋加 GB 数,得按真实访问模式反推:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 列出秒杀期间必读 Key 类型:
product:1001、sku:2005:stock、activity:seckill:config、user:12345:quota - 估算单 Key 平均大小:比如
product:1001JSON 约 2KB,100 个爆款就是 200KB;sku:*:stock是 string,通常 - 留出 30% 余量:Lua 脚本执行栈、临时排队集合(如
seckill:queue:2005)、客户端缓冲区都会吃内存 - 最终公式:
maxmemory = 静态基线 + (峰值活跃 Key 内存 × 1.3)。例如基线 1.2GB,预估新增 800MB,就设maxmemory 2.6gb
CONFIG SET 动态生效时最容易漏的两个参数
只改 maxmemory-policy allkeys-lfu 是半套配置,下面两个必须跟上,否则 LFU 基本等于没开:
-
lfu-log-factor:推荐设为15或20。值越大,计数器增长越慢,能抗住瞬时刷屏请求而不把爆款当“噪声”淘汰 -
lfu-decay-time:推荐设为1(分钟)。衰减太慢(如 30)会让历史高频但当前已下架的商品长期霸占内存;太快(如 0.1)又导致刚热起来的 Key 还没稳住就被踢 - 验证是否生效:
CONFIG GET lfu-log-factor和CONFIG GET lfu-decay-time必须看到你设的值,不是默认值
真正决定成败的是业务层怎么配合
Redis 不负责语义,只管内存。LFU 能力再强,也救不了设计混乱的 Key 生命周期:
- ✅ 适合“永不过期 + 逻辑过期”:
user:pref:789、config:feature:flag—— value 里塞{"exp": 1743790260, "data": {...}},由业务判断是否过期 - ❌ 绝对不能省 TTL:
seckill:token:abc123、order:lock:456789—— 这类必须用EXPIRE强保证,LFU 无法替代时效性 - ⚠️ 容易踩坑:把 session TTL 从 60s 改成 86400s 后,没配定时 job 清理
exp字段过期的 key,结果冷数据越积越多,evicted_keys几乎不涨,但used_memory持续缓慢爬升
最后提醒一句:所有配置变更后,盯紧 INFO memory 里的 mem_fragmentation_ratio 和 INFO stats 里的 evicted_keys 脉冲。抖动不是看平均延迟,是看有没有周期性尖峰。

















