冷缓存在高峰时最痛
重启、发布或手动清空会掏空缓存,随后所有请求同时未命中并打到数据库。如果热 key 集合已知,应在实例接收流量前预热。只预热有界集合,而不是整个数据集;加载一切的预热是自己制造的踩踏。
await mapLimit(hotKeys, 8, async (key) => {
if (await cache.exists(key)) return;
const value = await singleFlight(key, () => load(key));
await cache.set(key, JSON.stringify(value), { EX: 300 });
});
限制并发并去重
预热不应打开数百个数据库连接,也不应在多个实例间重复工作。限制并发,对重复 key 使用 single-flight,并考虑用分布式锁让一个实例只预热给定 key。若源站无法承受合并负载,应在实例间错开预热。
测量效果
比较冷启动时有预热和无预热后的缓存命中率与源站 QPS。在流量到达后才执行的预热无法阻止尖峰。把预热加入发布序列:启动进程、在时限内预热、再标记就绪。预热失败时决定是用冷缓存服务还是等待;不要无限期阻塞就绪。
验证预热
预期结果:预热完成后目标 key 存在于缓存,流量到来前命中率高于预热前基线,源站 QPS 保持在容量内。用缓存客户端抽样热 key,比较命中率指标与冷启动运行,并确认预热时长没有超过发布预算。仍然缺失的 key 通常意味着 TTL、序列化或 key 前缀不匹配。