缓存预热是冷启动阶段决定系统生死的关键动作,否则Redis缓存命中率趋近于0,数据库瞬间过载崩溃;需优先预热热点商品、运营配置、核心用户数据,并避免雪崩过期、阻塞启动、多实例并发写等执行陷阱。

缓存预热不是“锦上添花”,而是冷启动阶段决定系统生死的关键动作。 没预热的 Redis 服务在流量涌入瞬间,cache miss 率接近 100%,数据库直接受压,响应延迟飙升、连接池打满、甚至触发熔断——这不是性能下降,是服务失能。
为什么冷启动不预热,DB 就会崩
新实例启动后,Redis 中没有任何数据,第一个请求查 product:1001,没命中 → 查 MySQL → 写回 Redis;第二个请求来,还是没命中(因为刚写入的 key 还没被其他请求复用);千个并发进来,就是上千次 DB 查询。尤其当 SELECT * FROM product WHERE id IN (…) 这类批量查询被高频触发时,MySQL 的慢查询日志会立刻爆满。
常见错误现象包括:
- 应用启动后前 2 分钟内
mysql processlist中大量Sleep和Query状态连接堆积 - 监控平台显示
redis_hit_rate长期低于 10%,而db_qps是平时的 5–8 倍 - 用户反馈“首页加载慢”“商品详情打不开”,但接口日志里全是 200,掩盖了真实瓶颈
预热数据选哪些,比怎么预热更重要
全量预热既不可行也没必要——你不需要把 500 万商品都塞进 Redis,只要覆盖那 0.1% 的真实热点。选错数据,等于给消防车加满水却开去修路。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
必须优先加载的数据类型有:
-
product表中近 7 天pv > 5000的商品 ID(从 Nginx 日志或埋点 Kafka 流实时统计) - 首页 Banner、活动页跳转链接等运营强管控的
config:key类配置项 - 用户登录态依赖的
user:profile基础字段(如昵称、头像 URL),哪怕只预热 TOP 10000 用户 - 不预热
order:20260713*这类时间戳前缀的 key——它们天然不具备复用性
注意:expire 时间不能统一设为 3600。要对不同类别加随机偏移,比如 product:1001 设为 3600 + ThreadLocalRandom.current().nextInt(600),防止雪崩式集体过期。
预热执行时最容易被忽略的三个细节
很多团队写了预热脚本,但上线后仍踩坑,问题不在逻辑,而在执行上下文。
- 预热必须在
Spring Boot的@PostConstruct或ApplicationRunner中异步触发,**不能阻塞 main thread**;否则 Tomcat 启动卡住,K8s readiness probe 失败,Pod 被反复重启 - 使用
JedisPool时,预热前要先调用jedisPool.preparePool()或至少jedisPool.getResource()若干次,确保连接池已 warm up 到minIdle,否则预热本身就会因获取连接超时而失败 - 多实例部署时,**只允许一个节点执行预热**(通过 Redis 分布式锁或 ZooKeeper 选主),否则所有实例并发读 DB 写 Redis,DB 压力翻 N 倍,且可能写入重复或冲突数据
真正难的从来不是“怎么把数据塞进 Redis”,而是判断“此刻该塞哪几条”以及“塞进去之后谁来保证它不立刻失效”。预热不是一次性的初始化动作,它是和流量特征、业务节奏、数据更新链路深度耦合的持续过程——大促前两小时刷新一次,商品价格变更后秒级触发,这些才是压测时看不出、但线上凌晨三点会暴雷的关键点。


















