✅ 一、什么是数据预热?
定义:
在系统启动或业务前置阶段,提前将热点数据加载到缓存、内存、DB连接池、搜索引擎等中间件中,避免系统冷启动时的大量缓存未命中问题。
✅ 二、为什么需要数据预热?(面试可用答题逻辑)
问题场景 | 描述与后果 |
---|---|
缓存冷启动 | 系统重启/新部署节点时缓存为空 |
缓存穿透 | 热点数据被反复请求落到底层数据库 |
缓存击穿 | 某个高频 key 过期后,大量请求同时访问 |
缓存雪崩 | 大量 key 同时过期,系统被拖垮 |
✅ 数据预热的核心目标是:在用户访问之前,缓存就已经准备好热数据!
✅ 三、数据预热的典型方式
1️⃣ 启动时预热(推荐用于固定热点)
@Component
public class DataWarmUpRunner implements CommandLineRunner {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public void run(String... args) {
// 示例:加载首页热门商品
List<Goods> hotGoods = goodsService.queryTop10Hot();
for (Goods g : hotGoods) {
redisTemplate.opsForValue().set("goods::" + g.getId(), g, 10, TimeUnit.MINUTES);
}
}
}
📌 适合场景:固定热点数据(如:首页推荐、导航菜单等)
2️⃣ 定时任务预热(动态热点)
使用 @Scheduled
定时查询并加载数据(如前一天访问量前十的商品)。
@Scheduled(cron = "0 0/10 * * * ?")
public void preloadHotGoods() {
List<Long> hotIds = hotDataService.queryTopGoodsIds();
for (Long id : hotIds) {
Goods g = goodsService.getById(id);
redisTemplate.opsForValue().set("goods::" + id, g, 15, TimeUnit.MINUTES);
}
}
📌 优点:热数据自动学习并持续更新
📌 注意:要做好缓存雪崩/击穿保护(可加分布式锁、设置过期时间)
3️⃣ 热点探测 + 异步预热(智能型)
利用访问频率监控(如布隆过滤器/访问计数器)识别潜在热点,触发异步加载。
-
统计某商品 5 分钟内被访问超过 100 次 → 异步预热
-
使用消息队列或线程池异步执行
4️⃣ 运维手动预热(应急方案)
-
对某些大促前的 SKU / 商品 / 品牌,手动触发脚本
-
可以设计 Admin 接口或 Redis CLI 脚本
✅ 四、数据预热策略设计维度(架构面试加分)
维度 | 推荐实践 |
---|---|
缓存一致性 | 预热后设置合理过期时间 + 异步更新策略 |
热点识别方式 | 访问频率统计 / PV 排名 / 运维指定等 |
多级缓存层 | 本地缓存 + Redis(如 Caffeine + Redis) |
节点扩容预热 | 可结合 Nacos 通知扩容后调用接口拉取数据 |
高并发保护 | 加锁(如 Redisson)、设置随机过期时间 |
✅ 五、项目中典型数据预热实践举例
💼 示例:电商系统商品详情页
-
启动时预热:预加载首页 Top N 热门商品、广告 banner、品类导航
-
每小时定时任务:刷新爆品/特价商品缓存
-
商品详情页预热触发:用户搜索 → 未命中缓存 → MQ 异步加载 + 加 Redis 缓存
-
大促前运维通过管理后台设置预热 SKU 列表
✅ 六、面试答题模板(带场景)
Q:你们系统有没有做过缓存预热?怎么做的?
🧠 答题模板:
有的,在我们项目中,为了解决系统启动或高并发初期缓存命中率低导致的穿透问题,我们做了两种方式的数据预热:
第一是在系统启动后通过 CommandLineRunner 自动加载固定热点数据(如首页推荐、品牌榜);
第二是通过定时任务动态分析前一天热度数据定时更新 Redis 缓存;
此外,针对高并发访问的商品详情页,我们也做了访问量探测 + 异步预热机制,防止缓存击穿和雪崩。
多数预热数据缓存时限为 10~30 分钟,并加随机过期时间防止同一时间大量缓存失效。