Skip to content

MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据? ​

  • 标签:后端、场景题

🏛 业务架构师 ​

这道题我会先纠正一个隐含的错误目标:"保证 Redis 里都是热点数据"这个命题本身要重新定义。2000 万数据只放 20 万,说明 Redis 的定位就是"热点加速层"而不是"全量镜像"——追求的目标应该是命中率指标(>95%),而不是"精确控制哪 20 万在缓存"。

第一道防线:淘汰策略交给 Redis

  • allkeys-lru / allkeys-lfu:让 Redis 按访问模式自动保留热点
  • LFU(少频次淘汰)通常更符合业务:偶发的批量扫描(爬虫、报表)不会把真正的长期热点挤出去,LRU 会被一次冷数据遍历污染
  • 这是最省事也最稳健的方案——不要自己维护"谁是热点"的名单,访问模式千变万化(突然的热搜、大促切换主推品),人工/规则维护必滞后

第二道防线:预热与兜底

  • 核心数据(首页商品、主推活动)主动预热,避免冷启动命中率跳水把 DB 打挂
  • 缓存 miss 回源 DB 时加互斥锁/合并回源(singleflight),防止某个热 key 过期瞬间万箭齐发(缓存击穿)
  • 极热点 key 逻辑过期(value 里带过期时间,后台异步刷新),物理永不过期

架构师的核心观点:算账

  • 20 万数据扛住 2000 万总量的前提是访问符合二八甚至一九分布——电商、内容场景基本成立
  • 若业务是长尾访问(比如全量商品均匀被搜到),缓存层收益天然有限,加内存到 200 万也只是缓解;此时正确投资是把 DB 扛读能力做上去(读写分离、覆盖索引),而不是无限堆 Redis
  • 监控命中率 + 回源 QPS 两个指标,命中率掉说明访问模式变了,及时调容量——容量跟着命中率走,不跟感觉走

🏗 系统架构师 ​

这题的本质是缓存容量有限时如何做数据分级与准入控制,即"让 Redis 只装值得装的数据"。我分四步答。

1. 明确淘汰策略:让"热"自然浮现

  • 全量 2000w 数据放不进 20w 的 Redis,就依赖内存淘汰策略:allkeys-lru 或 allkeys-lfu。我强烈推荐 LFU(Redis 4.0+):点赞/阅读类访问分布里"偶发冷数据"会污染 LRU 链表,LFU 按访问频率统计,留下的是真热点
  • maxmemory 设为容量的 80% 留水位余量,触发淘汰有监控告警

2. 准入控制:冷数据干脆不进缓存 比"淘汰"更优雅的是"不加载":

  • 布隆过滤器前置:查询先过 Bloom(存全量 key),不存在直接穿透回源并计数,不存在者永不入 Redis——缓存里天然只留下"存在且被访问过"的候选热点
  • 基于业务语义的准入:只缓存近 7 天订单、活跃用户数据,历史冷数据查询直接走 DB(配合 DB 侧索引优化)

3. 热点探测与预热

  • 统计层算 TopN 热点 key(如按访问计数的小时榜),定时刷新进 Redis,保障确定性热点常驻
  • 大促前按业务清单预热(Top 商品、活动页),避免开闸瞬间缓存未命中率 100% 打爆 DB

4. 一致性配套:全量在 MySQL、热点在 Redis 的结构下,写操作用 Cache Aside(先更 DB 再删缓存)+ 短 TTL 兜底,即使淘汰与回源并发也不会长期脏读。

一句话:LFU 淘汰 + 布隆准入 + 热点预热的组合,让 20w 容量装下 90% 的访问。

💻 全栈开发专家 ​

两层数据只保证 Redis 里是热点:准入控制 + 淘汰策略 + 过期随机化。

1. 内存淘汰策略(保底)

conf
maxmemory 4gb                        -- 物理内存的 70~75%,留余量防 swap
maxmemory-policy allkeys-lru         -- 或 allkeys-lfu
  • allkeys-lru:通用选择,冷数据自动被挤出去。
  • allkeys-lfu(Redis 4+)更适合这题:按访问频率淘汰,偶发批量扫描的数据(访问一次就不再碰)不会污染缓存,长期热点能留住。可调 lfu-log-factor 控制计数增长速度。

2. 业务层准入(省钱又防污染)

20 万容量对 2000 万候选,"谁来配得上进缓存"要有门槛:

  • 只有被访问 ≥ 2 次的数据才升级进 Redis(先本地 Caffeine 短 TTL 当预筛选),一次性的长尾查询不值得占坑。
  • 写缓存用 SET key val EX ttl NX 语义,防止并发回源重复写入。

3. 过期策略防雪崩

  • TTL 加随机:ttl = base + random(600s),防止同一批数据同时过期引发回源风暴。
  • 热点 key 永不过期 + 后台异步刷新(逻辑过期),物理 TTL 做兜底保险丝。

4. 观测

  • redis-cli --hotkeys(配合 LFU)找真热点,info keyspace 看命中率;命中率低于 90% 就该审容量与准入策略。