🔥 2000w vs 20w:Redis 热点数据の生存锦标赛

MySQL 里有 2000w 条数据,但 Redis 内存只够存 20w — 谁是赢家?你说了算。

2000w
MySQL 存量数据
淘汰博弈
20w
Redis 内存上限

🎯 问题拆解 灵魂拷问

当你只有 20w 的「座位」,但有 2000w 「乘客」想进来 —— 你怎么办?

翻译成人话:Redis 内存就那么大,MySQL 里 2000w 条数据不可能全塞进去。你要是硬塞,Redis 脸一黑直接 OOM 给你看。

所以核心问题是:怎么让 Redis 里只留"最热"的 20w 条?

🏗️ 经典架构 三层缓冲区

👤 用户请求
🔴 Redis
热点数据 20w
miss →
🔵 MySQL
全量数据 2000w

读流程:

  1. 请求先打 Redis — 命中 → 直接返回,极速!
  2. Redis 没命中 — 去 MySQL 查
  3. MySQL 查到后 — 顺手写回 Redis(设置合理的过期时间)

⚠️ 关键:第三步「写回 Redis」如果内存满了,就会触发淘汰策略 — 这才是今天的重点!

🃏 Redis 6 种淘汰策略「全家桶」 速查表

Redis 4.0 以前只有 6 种,4.0 之后多了 LFU(后面会说)。先看这 6 个老伙计:

volatile

volatile-lru

从「设了过期时间」的 key 里,踢掉最久没用的那个

volatile

volatile-ttl

从「设了过期时间」的 key 里,踢掉 TTL 最短的那个

volatile

volatile-random

从「设了过期时间」的 key 里,闭眼随机踢一个 — 佛系淘汰

allkeys

allkeys-lru

从「所有 key」里挑最久没用的踢掉 — 不管你有没有过期时间

allkeys

allkeys-random

从「所有 key」里随机踢 — 听天由命流

驱逐禁令

no-eviction

一个都不踢!内存满了就报错 — 你写不进来关我屁事

✅ 正确答案 抄作业

🏆 首选方案:allkeys-lru 把不常访问的数据自动踢出,热数据自然留存。这是 Redis 为「缓存场景」量身定做的策略。

✅ allkeys-lru 为什么对?

  • 自动淘汰冷数据,热数据赖着不走
  • 不需要手动设置每个 key 的过期时间
  • 符合「二八定律」:80% 请求打在 20% 数据上
  • Redis 官方推荐作为缓存使用时的默认策略

❌ 其他策略为什么不对?

  • volatile 系列:只踢设过期时间的 key,不设过期时间的热数据也会霸占内存
  • no-eviction:内存满了直接拒绝写入,线上直接爆炸 💣
  • random 系列:可能把热数据随机踢掉,命中率暴跌

🚀 进阶升级:Redis 4.0+ 的 allkeys-lfu 黑科技

LRU 的致命弱点:只看「最近有没有用」,不看「用的频率」

举个栗子 🌰:某个 key 一小时前被狂刷 10000 次、但最近 5 分钟没人访问 — LRU 可能把它淘汰掉。但 LFU 知道它是高频热点,会手下留情。

维度 LRU LFU
判断依据 最近访问时间 访问频率 + 时间衰减
适用场景 常规缓存,无明显冷热分化 热点集中,二八分布明显 ✅
对本题适用性 ✅ 基本够用 🏆 最佳选择!

⚙️ 实操配置 上手指南

Step 1:设置最大内存

# redis.conf
maxmemory 2gb          # 根据你的 20w 数据量估算

Step 2:设置淘汰策略

# redis.conf — 推荐 allkeys-lfu (4.0+)
maxmemory-policy allkeys-lfu

# 或者降级到 allkeys-lru (更早版本)
maxmemory-policy allkeys-lru

Step 3:运行时动态修改(无需重启)

# 命令行直接改
CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lfu

🧩 完整方案 一句话总结

  1. 设置 maxmemory 根据 20w 条数据的实际大小(业务数据大小 × 20w × 1.5 倍冗余),配置 Redis 最大内存上限。别让它无限制吃内存,也别设太小浪费机器。
  2. 选 allkeys-lfu(或 allkeys-lru) 启用全局淘汰,让 Redis 自动把低频冷数据踢出去。热数据自然留下来了,不需要你手工管理。
  3. 设置合理的过期时间 写回 Redis 时,根据业务场景设 TTL(比如热门文章 1 小时、冷门商品 30 分钟)。作为 LRU/LFU 的双保险。
  4. 兜底:缓存穿透保护 对于 MySQL 里查不到的数据,也往 Redis 写一个空值(过期时间短一点),防止恶意请求把 MySQL 打穿。
💡 核心思想就一句话:别手动管 Redis 里该留啥、该踢啥 — 让 allkeys-lfu 自己算。你只管设好内存上限和过期时间,剩下的交给算法。

📋 太长不看版 TL;DR

🔴 Redis 设 maxmemory 2gb
🔴 淘汰策略选 allkeys-lfu
🔴 写缓存时加 TTL 过期时间
🔴 冷数据自动滚蛋,热数据自动留下
🔴 你唯一要做的:躺着看命中率蹭蹭涨 📈

🌲 策略选择决策树 一图流

🔴 Redis 是纯缓存?
├── → allkeys-lfu / allkeys-lru ✅
└── (部分数据不能丢)
├── 不能丢的数据别设过期 → 不用 volatile 系列 ❌
├── 缓存部分设过期 → volatile-lru / volatile-lfu
└── 实在内存不够 → 加机器、分片集群