题目:MySQL 里有 2000W 数据,Redis 中只存 20W 的数据,如何保证 Redis 中的数据都是热点数据?
难度:high
标签:redis/cache,mysql/hotspot
评分:⭐⭐⭐⭐☆(4/5)
保证 Redis 存的是热数据,先要判定什么是热数据,有两种方案。一是预先判定,根据历史数据分析和即将推广的活动推断可能的热数据并提前缓存。二是根据实际访问留存,用 LFU 做缓存回收控制热数据留存。淘汰可以按评估周期提前设置,或设置较短的 TTL 保证淘汰比例。热数据被淘汰后回源时,单线程加锁访问数据库,确保只有一个线程回源,不会并发大量线程压垮数据库。缓存穿透方面,基础方案是用布隆过滤器过滤不存在的异常访问;非大型项目一般直接缓存非正常数据并告警,如果某账户或 IP 有大量异常访问,就做封禁或直接返回非法。
优点:结构完整——先定义热、两套判定、淘汰、回填加锁、防穿透,四段闭环,是今天最好的一题。
不足:Redis 侧策略参数没落到具体配置;预测法缺反馈闭环;布隆不支持删除;漏了缓存雪崩(TTL 抖动)与降级限流。
补充:maxmemory-policy allkeys-lfu + lfu-log-factor / lfu-decay-time;容量按热点集 × value 大小 × 1.5 估;低峰预热 + 按实际 QPS 校准热门池。
「保证 Redis 里都是热点」是伪命题,真实目标是「用有限内存装下大部分访问」。三层:预测层(历史访问、活动计划、离线 TopN 预热点)→ 运行层(LFU/LRU 淘汰 + TTL,容量与命中率监控)→ 兜底层(回源 single-flight、防穿透、防雪崩、降级限流)。
hotkeys、客户端埋点统计。【一句话结论】 热点是动态的,方案必须是「预测 + 实时淘汰 + 回源保护」三层,而不是一次性灌 20 万。
【三点展开】 第一,预测层用历史访问和活动计划提前预热,运行层用 allkeys-lfu 加 TTL 让真实热点自然留下。第二,回源时用单飞锁,只放一个线程查库,其他线程等结果,避免击穿。第三,防穿透用布隆加空值缓存,防雪崩用 TTL 抖动和限流降级。
【一句边界】 如果热点集本身波动极大,20 万容量可能永远命中不了长尾,要接受一定回源率并保证回源路径可控。