Redis 内存淘汰策略
Redis 提供了多种 内存淘汰策略(Eviction Policy) ,用于在内存达到上限时决定如何删除数据,以便存入新的数据。我们详细介绍这些策略的 工作机制、适用场景、优缺点。
1. Redis 内存淘汰策略分类
当 Redis 内存达到 maxmemory 限制后,淘汰策略决定如何处理数据。Redis 的淘汰策略主要分为三大类:
- (1) 拒绝写入(不删除数据)
- (2) 仅淘汰带过期时间的 Key
- (3) 淘汰所有 Key
2. 具体的淘汰策略
(1) noeviction(拒绝写入)
- 机制 :当内存满时,Redis 不会删除任何 Key,而是直接返回错误。
- 适用场景 :适用于 缓存不允许丢失 的情况,例如会话管理 、金融交易数据等。
- 优点:
- 数据绝对安全,不会丢失任何 Key。
- 缺点:
- 可能导致 Redis 无法写入数据,影响业务正常运行。
- 适用于严格管控内存的场景,不适用于缓存(cache)用途。
(2) allkeys-lru(所有 Key 采用 LRU 淘汰)
- 机制 :在 所有 Key(无论是否有 TTL) 中,淘汰最近最少使用(Least Recently Used, LRU)的 Key。
- 适用场景 :适用于 普通缓存,例如 Web 页面缓存、短期存储等。
- 优点:
- 能够自动保留 最近访问的热点数据,提升缓存命中率。
- 缺点:
- 需要额外的 LRU 计算开销(但 Redis 内部已做优化)。
(3) volatile-lru(仅带过期时间的 Key 采用 LRU 淘汰)
- 机制:只淘汰**带 TTL(过期时间)**的 Key,按照 LRU 规则删除最少使用的 Key。
- 适用场景 :适用于数据有明确过期时间的缓存(如 Web 页面缓存、令牌管理)。
- 优点:
- 不会影响永久存储的数据(无 TTL 的 Key)。
- 缺点:
- 如果带 TTL 的 Key 很少,或者都还未过期,可能导致无法释放足够的内存,最终 Redis 仍然会写入失败。
(4) allkeys-random(所有 Key 随机淘汰)
- 机制 :在所有 Key 中随机选择一些 Key 进行淘汰,不管是否有 TTL。
- 适用场景:适用于不要求缓存命中率的场景,如临时性存储、非核心数据。
- 优点:
- 低计算开销,不需要维护访问频率信息。
- 缺点:
- 缓存命中率较低,可能会删除热点数据,导致 Redis 效率下降。
(5) volatile-random(仅带过期时间的 Key 随机淘汰)
- 机制 :只淘汰 带 TTL 的 Key,随机选择一部分 Key 进行删除。
- 适用场景 :适用于缓存系统,数据有过期时间,但访问频率无规律。
- 优点:
- 避免删除无 TTL 的数据。
- 缺点:
- 删除不够智能,可能误删热点数据,影响缓存命中率。
(6) volatile-ttl(仅带过期时间的 Key,优先淘汰 TTL 最短的)
- 机制 :在所有带 TTL 的 Key 中,优先删除 TTL 最短的 Key。
- 适用场景 :适用于有明确过期时间的数据(如定期缓存的数据、会话管理)。
- 优点:
- 使即将过期的数据优先被删除,符合一般业务逻辑。
- 缺点:
- 如果 TTL 设定不合理(比如大量 Key 过期时间相同),仍可能影响命中率。
3. Redis 6.0+ 的 LFU 淘汰策略
Redis 6.0 引入了 LFU(Least Frequently Used) 淘汰策略,进一步优化 LRU 算法。
(7) allkeys-lfu(所有 Key 采用 LFU 淘汰)
- 机制 :在 所有 Key 中,淘汰访问最少的 Key。
- 适用场景 :适用于热点数据变化较快的场景,如新闻推荐、个性化广告缓存等。
- 优点:
- 能够自动保留最常访问的 Key,比 LRU 更智能。
- 缺点:
- 计算代价比 LRU 高,但 Redis 内部做了优化(基于近似计数)。
(8) volatile-lfu(仅带 TTL 的 Key 采用 LFU 淘汰)
- 机制 :在带 TTL 的 Key 中,淘汰访问最少的 Key。
- 适用场景 :适用于 对缓存命中率要求高,且数据带过期时间 的情况。
- 优点:
- 不会误删无 TTL 的 Key ,并且优先保留访问频率高的 Key。
- 缺点:
- 计算开销较高,但 Redis 6.0 进行了优化。
4. 淘汰策略对比总结
淘汰策略 | 适用范围 | 适用场景 | 优点 | 缺点 |
---|---|---|---|---|
noeviction(默认淘汰策略) |
所有 Key | 数据不能丢失的场景(如金融系统) | 数据安全,不丢失 | 可能导致 Redis 写入失败 |
allkeys-lru |
所有 Key | 普通缓存(如 Web 缓存) | 适应热点数据变化,缓存命中率高 | 需要维护 LRU |
volatile-lru |
仅带 TTL | 数据有明确过期时间的缓存 | 避免删除永久存储的数据 | 若带 TTL 的 Key 很少,可能无法释放足够内存 |
allkeys-random |
所有 Key | 临时存储(不要求命中率) | 计算简单 | 缓存命中率低 |
volatile-random |
仅带 TTL | 随机淘汰缓存数据 | 计算简单 | 可能误删热点数据 |
volatile-ttl |
仅带 TTL | 定期缓存数据(如会话管理) | 优先删除即将过期的数据 | TTL 设定不合理可能影响命中率 |
allkeys-lfu |
所有 Key | 热点数据变化快(如推荐系统) | 优先保留高频访问数据 | 计算比 LRU 略高 |
volatile-lfu |
仅带 TTL | 高频访问缓存(如广告缓存) | 同时考虑访问频率和 TTL | 计算比 LRU 略高 |
5. 选择合适的策略
- 数据不能丢失 ➝
noeviction
- 普通缓存,保留热点数据 ➝
allkeys-lru
- 数据有过期时间,保留热点数据 ➝
volatile-lru
- 不在意命中率,只要释放内存 ➝
allkeys-random
- 热点数据变化快,使用频率高 ➝
allkeys-lfu
- 仅对带 TTL 的 Key 进行优化 ➝
volatile-ttl
/volatile-lfu
总结
Redis 采用 LRU、LFU、TTL、随机淘汰 等方式,适应不同场景,合理选择淘汰策略,可以提高 缓存命中率 和 数据管理效率。