Skip to content

Redis 中有哪些内存淘汰策略? ​

  • 标签:后端、Redis

🏛 业务架构师 ​

八种淘汰策略,本质是回答"内存满了,牺牲谁"——这是业务价值排序题:

  • noeviction(默认):不淘汰,写请求报错。适合 Redis 承载不可丢数据(分布式锁的锁标记、计数器)——宁可拒绝写入也不能静默丢。但用于纯缓存场景就是事故:内存一满整个应用的写全报错;
  • allkeys-lru / allkeys-lfu / allkeys-random:全量 key 中按策略淘汰——纯缓存场景的标准选择;
  • volatile-lru / volatile-lfu / volatile-random / volatile-ttl:只在设置了过期时间的 key 里淘汰——混合场景:同一实例既有缓存(可丢)又有状态数据(不可丢,不设 TTL),淘汰只动缓存。

LRU 与 LFU 的选择是业务访问模式判断:LRU 淘汰"最近没用",适合时间局部性强的数据(新闻、会话);LFU 淘汰"总体用得少",防"偶发批量扫描把热数据挤掉"——偶发的大任务(报表、迁移)扫过全量 key,LRU 会把真正的热点洗掉,LFU 顶得住。

我的落地三条:

  1. 先分类再选策略:一个实例里混放"可丢缓存"和"不可丢状态"是设计坏味道——按数据性质拆实例(缓存实例 allkeys-lru,状态实例独立部署),比依赖 volatile- 前缀策略更清晰可靠;
  2. maxmemory 要设:默认 0(不限制)= 用到机器内存被 OOM killer 干掉,Redis 挂比淘汰更伤;
  3. 淘汰配合监控:evicted_keys 指标上涨 = 容量不足信号,淘汰是兜底不是常态,长期高淘汰说明该扩容或加 TTL。

一句话:淘汰策略 = 内存压力下"丢什么"的业务声明,数据分级是前置作业。

🏗 系统架构师 ​

Redis 内存达到 maxmemory 后的回收策略(maxmemory-policy,8 种),我分三组记:

noeviction(默认):不淘汰,写命令直接报 OOM 错误。纯缓存含义的实例用它等于把故障抛给业务——我一般不让生产实例保持默认。

allkeys-*(全体 key 参与):

  • allkeys-lru:近似 LRU(采样 5 个 key 淘汰最久未用,可调 maxmemory-samples),通用缓存首选;
  • allkeys-lfu(4.0+):按访问频率(对数计数器 + 衰减),比 LRU 更抗"偶发批量扫描污染"——一次全表扫描会把 LRU 的历史信息冲掉,LFU 不受影响,热点缓存我更推 LFU;
  • allkeys-random:随机,几乎不用。

volatile-*(仅带 TTL 的 key):volatile-lru / volatile-lfu / volatile-random / volatile-ttl(快过期的先淘汰)。前提是所有 key 都设了过期,否则无 TTL 的 key 永不淘汰仍会 OOM。

我的实践配置:纯缓存实例 allkeys-lfu + maxmemory 设物理内存 70~80%;混合实例(有持久状态)用 volatile-* 并强制"可缓存数据必须带 TTL";同时监控 evicted_keys 增速——淘汰速率暴增说明容量不足或过期策略没生效,是容量扩容的先行指标。注意 LRU/LFU 是采样的近似实现,换来的是 O(1) 淘汰成本不阻塞主线程,工程上这笔账很划算。

💻 全栈开发专家 ​

8 种策略,按"内存满了怎么办"分两类:

不淘汰(1 种):

  • noeviction(默认):拒绝写入(报 OOM 错误),读不受影响。默认值是坑:当缓存用却没改配置,内存满后所有写报错,应用一片异常。

全量 key 中淘汰(3 种):

  • allkeys-lru:近似 LRU(随机采样 5 个 key 淘汰最久未用,可调 maxmemory-samples);
  • allkeys-lfu(4.0+):按访问频率,自带计数衰减,热点保留更好;
  • allkeys-random:随机,几乎不用。

只在设置了过期时间的 key 中淘汰(4 种):

  • volatile-lru / volatile-lfu / volatile-random / volatile-ttl(优先淘汰快过期的)。

我的选型:

conf
maxmemory 4gb
maxmemory-policy allkeys-lfu    # 纯缓存实例
  • 纯缓存:allkeys-lru 或 allkeys-lfu,前者通用,后者有明显热点时更优(LFU 不会被偶发的全量扫描"洗掉"热点);
  • 缓存 + 少量不可丢数据共存:不可丢的 key 不设 TTL + 用 volatile-lru——但我不推荐混用,缓存和存储分开部署才是正解;
  • noeviction 只给当存储用的实例(配合容量监控)。

运维提醒:改 policy 是 CONFIG SET 即时生效;淘汰数看 info stats 的 evicted_keys,持续增长说明容量不足或 TTL 设计有问题,别等业务报错才发现。