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 顶得住。
我的落地三条:
- 先分类再选策略:一个实例里混放"可丢缓存"和"不可丢状态"是设计坏味道——按数据性质拆实例(缓存实例 allkeys-lru,状态实例独立部署),比依赖 volatile- 前缀策略更清晰可靠;
- maxmemory 要设:默认 0(不限制)= 用到机器内存被 OOM killer 干掉,Redis 挂比淘汰更伤;
- 淘汰配合监控: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 设计有问题,别等业务报错才发现。