Redis 内存淘汰策略共 8 种,分两大类:不淘汰和淘汰数据;
纯缓存场景优先选 allkeys-lru,混合场景选 volatile-lru,数据不能丢的话选 noeviction。
maxmemory 参数
只有设置了 maxmemory(Redis 最大内存限制),内存淘汰策略才会生效。
设置 maxmemory的两种方式
- 配置文件
redis.conf:
nginx
# 限制 Redis 最大使用 1GB 内存
maxmemory 1gb
- 命令行动态设置(重启后会失效):
bash
127.0.0.1:6379> CONFIG SET maxmemory 1gb
Redis 的8种内存淘汰策略
可以分为两大类:
| 大类 | 策略名称 | 含义 |
|---|---|---|
| 不淘汰数据 | noeviction |
内存满了,新写入直接报错,不淘汰任何数据 |
| 淘汰过期键 | volatile-lru |
淘汰设置了过期时间的键中,最近最少使用的 |
volatile-lfu |
淘汰设置了过期时间的键中,最不经常使用的 | |
volatile-ttl |
淘汰设置了过期时间的键中,即将过期的 | |
volatile-random |
随机淘汰设置了过期时间的键 | |
| 淘汰所有键 | allkeys-lru |
淘汰所有键 中,最近最少使用的 |
allkeys-lfu |
淘汰所有键 中,最不经常使用的 | |
allkeys-random |
随机淘汰所有键 |
1. noeviction
当内存满了,新写入的请求(比如 SET、LPUSH)会直接报错 (error) OOM command not allowed when used memory > 'maxmemory',不淘汰任何数据。
适用于数据绝对不能丢,且有完善的内存监控和扩容机制(比如金融级核心数据)的场景。
2. 淘汰过期键的4种策略
这类策略只淘汰设置了 expire 过期时间的键,不会碰永久键,适合"缓存+持久化"混合的场景(比如永久键存重要数据,过期键存缓存)。
volatile-lru
LRU = Least Recently Used(最近最少使用)。
在设置了过期时间的键中,淘汰最久没被访问过的键。
比如缓存场景,往往会希望保留"最近刚用过的热数据"。
volatile-lfu
LFU = Least Frequently Used(最不经常使用)。
在设置了过期时间的键中,淘汰访问次数最少的键。
volatile-ttl
TTL = Time To Live(剩余生存时间)。
在设置了过期时间的键中,淘汰剩余时间最短、即将过期的键。
volatile-random
在设置了过期时间的键中,随机淘汰一个。
3. 淘汰所有键的3种策略
这类策略不管键有没有设置过期时间,都会淘汰,适合纯缓存场景(所有数据都是缓存,丢了也没关系,可以从数据库重新加载)。
allkeys-lru
在所有键中,淘汰最近最少使用的键。
比较适合电商商品缓存、用户Session缓存这些纯缓存场景。
allkeys-lfu
在所有键中,淘汰访问次数最少的键。
allkeys-random
在所有键中,随机淘汰一个。
LRU vs LFU,到底有啥区别?
| 对比维度 | LRU(最近最少使用) | LFU(最不经常使用) |
|---|---|---|
| 核心依据 | 看最近多久没被访问 | 看访问次数多少 |
| 优点 | 实现简单,符合"热数据最近常用"的直觉 | 更精准,能识别"真正的热数据"(比如某个键虽然最近没被访问,但总访问次数极高) |
| 缺点 | 可能误删"偶尔访问一次的冷数据,但其实总访问次数很高" | 实现复杂,需要额外空间记录访问次数 |
举个例子
假设键A昨天被访问100次,今天没被访问;
键B今天被访问1次。
因为最近没被访问,所以LRU会删键A。
但是,因为总访问次数只有1次,所以LFU会删键B。