秒杀开始前内存爆了是因为缓存未预热。大量页面请求触发冷数据批量加载,叠加noeviction或lru策略缺陷导致oom;需用allkeys-lfu策略、精准扩容maxmemory并提前pipeline预热爆款key。

秒杀开始前内存就爆了?不是QPS太高,是缓存没“预热”好。
为什么秒杀一开,Redis内存就飙升甚至OOM?
秒杀流量进来时,并非所有请求都打在库存扣减上——大量用户会反复刷商品页、详情页、倒计时、下单页。这些页面依赖的product:1001、sku:2005:stock、activity:seckill:config等Key会被密集读取,但若这些Key之前不在内存里,就会触发批量加载(尤其是带关联数据的聚合查询),瞬间把冷数据全塞进Redis,撑爆maxmemory。
更关键的是:默认的noeviction策略会让写入失败直接报错;而allkeys-lru可能把刚加载的爆款商品Key又踢掉,导致下一轮请求再次回源,形成“加载→淘汰→再加载”的恶性循环。
提前扩容maxmemory必须配合业务水位预估
不能只看当前内存使用率。要按秒杀峰值期间的「缓存覆盖范围」反推:
- 列出所有必缓存Key类型:商品基础信息、SKU库存、活动规则、用户限购状态、订单草稿(如需)
- 估算单个Key平均大小(例如
product:1001JSON约2KB,100个爆款就是200KB) - 预估并发访问的Key组合数:比如10万用户同时刷前20个爆款SKU,对应
sku:*:stock最多活跃200个,而非全部1000个 - 留出30%余量——因为Lua脚本执行、临时集合(如排队队列)、客户端连接缓冲也会吃内存
最终maxmemory建议设为:「静态缓存基线 + 峰值动态Key内存 × 1.3」。例如基线1.2GB,预估峰值新增800MB,则设maxmemory 2.6gb。
allkeys-lfu比allkeys-lru更适合秒杀场景
allkeys-lfu淘汰的是“长期访问频次最低”的Key,而不是“最近最少用”的Key。这对秒杀很关键:
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
— 爆款商品(如sku:2005:stock)在预热后被高频读取,LFU计数器会持续上升,极难被淘汰;
— 长尾商品或已结束活动的配置Key访问骤降,自然成为淘汰候选;
— 避免了LRU在突发流量下把“刚热起来的爆款”误判为“冷Key”而踢出的问题。
注意两个实操细节:
- 必须启用
lfu-log-factor(推荐设为10),否则默认因子1会导致计数器增长过慢,无法区分真实热度差异 - 不要调
lfu-decay-time太小(如设为1),否则计数器衰减过快,会削弱LFU的长期统计意义 - 验证方式:秒杀中用
redis-cli --hotkeys观察实际热点,确认爆款Key的freq值显著高于其他Key
光设策略不够,得让爆款Key“提前住进来”
内存扩容和淘汰策略只是兜底。真正要稳,得在秒杀开始前主动加载核心Key:
- 用
pipeline批量GET所有爆款商品和SKU的完整数据,强制载入内存 - 对库存Key,用
INCRBY或SET写入初始值(哪怕只是模拟一次读),触发LFU计数器初始化 - 避免用
MGET加载混合大小Key——大Key(如含图片URL的商品详情)可能挤占小Key空间,应拆分缓存粒度 - 预热脚本最好在秒杀前10分钟执行,并监控
used_memory_peak是否平稳收敛
真正的风险点不在“能不能扛住QPS”,而在于“缓存是否在第一秒就处于最优状态”。LFU+预热+精准的maxmemory设定,三者缺一不可——少一个,超卖或500错误就藏在第1001个请求里。










