Redis 内存淘汰策略
1. 为什么需要内存淘汰
Section titled “1. 为什么需要内存淘汰”Redis 是内存数据库,内存是有限资源。当内存使用达到 maxmemory 上限时,Redis 需要按照配置的淘汰策略决定如何处理新的写入请求。
内存使用 < maxmemory:正常写入
内存使用 = maxmemory: │ ▼ 触发淘汰策略 │ ├── 有可淘汰的 key ──▶ 删除部分 key,腾出空间,写入成功 └── 无可淘汰的 key ──▶ 返回 OOM 错误,写入失败2. 配置最大内存
Section titled “2. 配置最大内存”maxmemory 2gb # 最大使用内存,0 = 不限制(生产必须配置)maxmemory-policy allkeys-lru # 淘汰策略# 运行时动态修改CONFIG SET maxmemory 4gbCONFIG SET maxmemory-policy allkeys-lru3. 八种淘汰策略
Section titled “3. 八种淘汰策略”3.1. 策略速查表
Section titled “3.1. 策略速查表”| 策略 | 淘汰范围 | 淘汰方式 | 推荐场景 |
|---|---|---|---|
noeviction | — | 不淘汰,直接报错 | 不允许任何数据丢失 |
allkeys-lru | 全部 key | 最近最少使用(LRU) | 通用缓存 ✅ |
allkeys-lfu | 全部 key | 最不常用(LFU) | 访问频率差异大的缓存 ✅ |
allkeys-random | 全部 key | 随机淘汰 | 均匀访问,无冷热区分 |
volatile-lru | 设置了 TTL 的 key | 最近最少使用 | 混合存储(缓存+持久数据) |
volatile-lfu | 设置了 TTL 的 key | 最不常用 | 混合存储,按频率淘汰 |
volatile-random | 设置了 TTL 的 key | 随机淘汰 | 混合存储,无差别淘汰 |
volatile-ttl | 设置了 TTL 的 key | TTL 越小越先淘汰 | 优先清理即将过期的 key |
3.2. 策略分类示意
Section titled “3.2. 策略分类示意”按淘汰范围分:├── allkeys-xxx ──▶ 所有 key 都可被淘汰└── volatile-xxx ──▶ 只淘汰有 TTL 的 key(无 TTL 的 key 永不被淘汰)
按淘汰方式分:├── lru ──▶ Least Recently Used(最近最少访问)├── lfu ──▶ Least Frequently Used(访问频率最低)├── random ──▶ 随机└── ttl ──▶ 剩余生存时间最短4. LRU vs LFU
Section titled “4. LRU vs LFU”4.1. LRU(最近最少使用)
Section titled “4.1. LRU(最近最少使用)”淘汰最长时间未被访问的 key,基于时间维度:
访问记录(时间从早到晚):A ──▶ B ──▶ C ──▶ A ──▶ D
LRU 链表(最近访问在右):B ──▶ C ──▶ A ──▶ D↑最久未访问,优先淘汰 B
问题:热点数据偶尔一次长时间未访问,会被误淘汰场景:A 是热点数据,但最近正好没被访问 → 被 LRU 错误淘汰4.2. LFU(最不常用)
Section titled “4.2. LFU(最不常用)”淘汰访问频率最低的 key,基于频率维度:
访问频率统计:A: 100次 B: 5次 C: 200次 D: 1次
LFU 淘汰顺序:D(1) → B(5) → A(100) → C(200)
优势:热点数据访问频率高,不会被误淘汰问题:新加入的 key 频率为 0,容易被立即淘汰解决:Redis 为新 key 设置初始频率计数(默认 5),避免立即被淘汰4.3. 对比
Section titled “4.3. 对比”| 对比项 | LRU | LFU |
|---|---|---|
| 依据 | 最后访问时间 | 访问频率计数 |
| 热点数据保护 | 一般(长时间未访问会被淘汰) | 好(高频数据优先保留)✅ |
| 新数据保护 | 好(刚加入时间戳最新) | 一般(新数据频率低,易被淘汰) |
| 内存额外开销 | 小(仅记录时间戳) | 略大(记录频率计数) |
| 推荐场景 | 访问时间局部性强(最近访问的更可能再被访问) | 冷热数据差异明显,热点稳定 |
5. 如何选择策略
Section titled “5. 如何选择策略”Redis 只做缓存(所有数据可重建)? └──▶ allkeys-lru(通用)或 allkeys-lfu(热点稳定)
Redis 混合存储(部分数据不能丢)? └──▶ volatile-lru / volatile-lfu (只淘汰有 TTL 的缓存数据,无 TTL 的持久数据不受影响)
不允许任何数据被淘汰(宁可报错也不丢数据)? └──▶ noeviction(写满后新写入直接报 OOM 错误)
按 TTL 优先淘汰即将过期的 key? └──▶ volatile-ttl生产环境最常用的两种策略:
纯缓存场景(绝大多数业务): maxmemory-policy allkeys-lru
热点稳定、需要精确保护高频数据: maxmemory-policy allkeys-lfu6. 内存优化实践
Section titled “6. 内存优化实践”6.1. 查看内存使用情况
Section titled “6.1. 查看内存使用情况”# 查看内存统计INFO memory
# 关键指标:# used_memory:实际使用内存# used_memory_rss:操作系统分配的内存(含碎片)# mem_fragmentation_ratio:内存碎片率(> 1.5 说明碎片严重)# maxmemory:配置的最大内存6.2. 查找大 key
Section titled “6.2. 查找大 key”# 扫描大 key(非阻塞)redis-cli -a 123456 --bigkeys
# 分析各数据类型的内存分布redis-cli -a 123456 --memkeys6.3. 内存碎片处理
Section titled “6.3. 内存碎片处理”# Redis 4.0+ 支持在线碎片整理CONFIG SET activedefrag yesCONFIG SET active-defrag-ignore-bytes 100mb # 碎片超过 100MB 才整理CONFIG SET active-defrag-enabled yes6.4. 配置建议
Section titled “6.4. 配置建议”# redis.conf 生产推荐配置maxmemory 6gb # 留 2GB 给系统,总内存 8GB 时设 6GBmaxmemory-policy allkeys-lru # 纯缓存场景maxmemory-samples 10 # LRU/LFU 采样数,越大越精确(默认 5)
# LFU 相关(使用 allkeys-lfu 时)lfu-log-factor 10 # 频率计数增长速率,越大增长越慢(默认 10)lfu-decay-time 1 # 频率计数衰减时间(分钟,默认 1)