跳转到内容

Redis 内存淘汰策略


Redis 是内存数据库,内存是有限资源。当内存使用达到 maxmemory 上限时,Redis 需要按照配置的淘汰策略决定如何处理新的写入请求。

内存使用 < maxmemory:正常写入
内存使用 = maxmemory:
触发淘汰策略
├── 有可淘汰的 key ──▶ 删除部分 key,腾出空间,写入成功
└── 无可淘汰的 key ──▶ 返回 OOM 错误,写入失败
redis.conf
maxmemory 2gb # 最大使用内存,0 = 不限制(生产必须配置)
maxmemory-policy allkeys-lru # 淘汰策略
Terminal window
# 运行时动态修改
CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru

策略淘汰范围淘汰方式推荐场景
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 的 keyTTL 越小越先淘汰优先清理即将过期的 key
按淘汰范围分:
├── allkeys-xxx ──▶ 所有 key 都可被淘汰
└── volatile-xxx ──▶ 只淘汰有 TTL 的 key(无 TTL 的 key 永不被淘汰)
按淘汰方式分:
├── lru ──▶ Least Recently Used(最近最少访问)
├── lfu ──▶ Least Frequently Used(访问频率最低)
├── random ──▶ 随机
└── ttl ──▶ 剩余生存时间最短

淘汰最长时间未被访问的 key,基于时间维度:

访问记录(时间从早到晚):
A ──▶ B ──▶ C ──▶ A ──▶ D
LRU 链表(最近访问在右):
B ──▶ C ──▶ A ──▶ D
最久未访问,优先淘汰 B
问题:热点数据偶尔一次长时间未访问,会被误淘汰
场景:A 是热点数据,但最近正好没被访问 → 被 LRU 错误淘汰

淘汰访问频率最低的 key,基于频率维度:

访问频率统计:
A: 100次 B: 5次 C: 200次 D: 1次
LFU 淘汰顺序:D(1) → B(5) → A(100) → C(200)
优势:热点数据访问频率高,不会被误淘汰
问题:新加入的 key 频率为 0,容易被立即淘汰
解决:Redis 为新 key 设置初始频率计数(默认 5),避免立即被淘汰
对比项LRULFU
依据最后访问时间访问频率计数
热点数据保护一般(长时间未访问会被淘汰)好(高频数据优先保留)✅
新数据保护好(刚加入时间戳最新)一般(新数据频率低,易被淘汰)
内存额外开销小(仅记录时间戳)略大(记录频率计数)
推荐场景访问时间局部性强(最近访问的更可能再被访问)冷热数据差异明显,热点稳定

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-lfu

Terminal window
# 查看内存统计
INFO memory
# 关键指标:
# used_memory:实际使用内存
# used_memory_rss:操作系统分配的内存(含碎片)
# mem_fragmentation_ratio:内存碎片率(> 1.5 说明碎片严重)
# maxmemory:配置的最大内存
Terminal window
# 扫描大 key(非阻塞)
redis-cli -a 123456 --bigkeys
# 分析各数据类型的内存分布
redis-cli -a 123456 --memkeys
Terminal window
# Redis 4.0+ 支持在线碎片整理
CONFIG SET activedefrag yes
CONFIG SET active-defrag-ignore-bytes 100mb # 碎片超过 100MB 才整理
CONFIG SET active-defrag-enabled yes
# redis.conf 生产推荐配置
maxmemory 6gb # 留 2GB 给系统,总内存 8GB 时设 6GB
maxmemory-policy allkeys-lru # 纯缓存场景
maxmemory-samples 10 # LRU/LFU 采样数,越大越精确(默认 5)
# LFU 相关(使用 allkeys-lfu 时)
lfu-log-factor 10 # 频率计数增长速率,越大增长越慢(默认 10)
lfu-decay-time 1 # 频率计数衰减时间(分钟,默认 1)