缓存预热策略:让缓存”热”起来
什么是缓存预热
缓存预热(Cache Warming / Pre-heating)是指系统上线或重启后,在正式对外提供服务之前,主动将热点数据加载到缓存中的过程。目的是避免缓存刚启动时”冷启动”状态下大量请求穿透到数据库。
为什么需要缓存预热
缓存服务刚启动时是空的(或者 Redis 重启、集群扩容、缓存大面积失效后),此时没有任何数据在缓存中。如果直接开放流量:
- 缓存雪崩:大量请求同时穿透到数据库,导致数据库被打垮
- 服务超时:数据库扛不住压力,服务响应变慢甚至不可用
- 慢启动现象:上线后的前几分钟请求延迟明显偏高
缓存预热就是为了消除这个”冷启动”窗口。
常用预热策略
1. 定时预热(离线脚本)
系统上线或低峰期,通过脚本批量查询数据库,将热点数据写入缓存。
# 预热脚本示例
redis-cli -h localhost -p 6379 MSET \
user:1001 "$(cat data/user_1001.json)" \
user:1002 "$(cat data/user_1002.json)" \
product:2001 "$(cat data/product_2001.json)"
优点:实现简单,可以在上线前单独执行
缺点:数据新鲜度依赖脚本更新的时机
2. 懒加载预热(启动时加载)
应用启动时,在 @PostConstruct 或 ApplicationRunner 中执行预热逻辑:
@Component
public class CacheWarmer {
@Autowired private RedisTemplate redis;
@Autowired private HotDataService hotDataService;
@PostConstruct
public void warmUp() {
// 加载 Top 10000 热点商品
List<HotProduct> topProducts = hotDataService.getTopProducts(10000);
topProducts.parallelStream().forEach(p -> {
redis.opsForValue().set("product:" + p.getId(),
JSON.toJSONString(p), 30, TimeUnit.MINUTES);
});
log.info("缓存预热完成,共加载 {} 条热点数据", topProducts.size());
}
}
优点:自动化,重启即预热
缺点:增加启动时间,预热完成前服务不应接受流量
3. 流量驱动的渐进式预热
不主动加载,而是在缓存未命中时,通过限流和互斥锁机制控制穿透流量:
public String getWithWarmUp(String key) {
String value = redis.opsForValue().get(key);
if (value != null) return value;
// 使用分布式锁,只有一个线程回源
String lockKey = "lock:" + key;
if (redis.opsForValue().setIfAbsent(lockKey, "1", 3, TimeUnit.SECONDS)) {
try {
value = loadFromDB(key);
redis.opsForValue().set(key, value, 30, TimeUnit.MINUTES);
} finally {
redis.delete(lockKey);
}
} else {
// 等待其他线程加载
Thread.sleep(100);
return redis.opsForValue().get(key);
}
return value;
}
优点:不需要提前规划热点数据,自然适应流量变化
缺点:预热阶段仍然会有少量请求穿透
4. 读写穿透预热(缓存预热服务)
使用一个独立的数据同步服务,监听数据库变更并实时同步到缓存。适用于数据实时性要求高的场景,比如使用 Canal 监听 MySQL binlog:
MySQL → Canal → Kafka → 预热消费者 → Redis
优点:数据实时同步,缓存与数据库几乎一致
缺点:架构复杂,引入额外中间件
预热策略的选择
| 策略 | 适用场景 | 复杂度 |
|---|---|---|
| 离线脚本 | 静态数据、配置类数据 | 低 |
| 启动加载 | 热点列表明确的场景 | 中 |
| 流量驱动 | 热点不确定、长尾流量 | 中 |
| 读写穿透 | 强一致性要求、实时性强 | 高 |
最佳实践
- 分优先级预热:核心数据先预热,非核心延后
- 错开过期时间:预热时设置不同的 TTL,避免集中失效
- 监控预热进度:记录预热耗时、加载条数、缓存命中率提升效果
- 预热不要压垮 DB:控制并发度,特别是启动加载时
- 结合流量预估:根据历史 QPS 预估预热数据量级
面试要点
- 说清缓存预热的本质是把冷缓存变热,防止启动期间的穿透
- 能举出实际预热方案,并说出优缺点
- 最好能提到”预热时间要控制在优雅停机窗口内”
- 对大型系统可以提到”全量预热 + 增量同步”的组合策略
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容