Redis淘汰策略
Redis 为什么需要淘汰策略?
Redis 是一个基于内存的数据库/缓存,当实际使用的内存量超过 maxmemory 参数设置的最大限制时,Redis 会根据配置的淘汰策略(Eviction Policy) 来移除一些键,以便为新数据腾出空间。
Redis 的淘汰策略有哪些?
Redis 提供了 8 种淘汰策略,可以分为两大类:
第一类:处理过期键的策略(只针对设置了 TTL 过期的键)
这组策略只在有过期时间的键中进行淘汰。
volatile-lru (Least Recently Used)
- 机制:从设置了过期时间的键中,淘汰最近最少使用的键。
- 理解:基于时间戳,认为最近没被访问的键以后也不太可能被访问。
volatile-lfu (Least Frequently Used)
- 机制:从设置了过期时间的键中,淘汰最不经常使用的键。
- 理解:基于访问频率计数器,认为访问次数最少的键是最不重要的。这是 Redis 4.0 及以上版本新增的策略。
volatile-random
- 机制:从设置了过期时间的键中,随机淘汰某个键。
- 理解:简单粗暴,没有开销,但效果不确定。
volatile-ttl
- 机制:从设置了过期时间的键中,淘汰存活时间最短(TTL 最小)的键,即即将过期的键。
- 理解:优先清理马上要过期的数据,尽量保留还有很久才过期的数据。
第二类:在所有键中进行的策略(包括无过期时间的键)
这组策略会在所有键中进行淘汰,无论是否设置了 TTL。这是最常用的策略类型,因为它能防止没有设置 TTL 的键导致内存爆满。
allkeys-lru
- 机制:从所有键中,淘汰最近最少使用的键。
- 理解:这是最常用的策略之一,非常适合作为缓存系统使用。
allkeys-lfu
- 机制:从所有键中,淘汰最不经常使用的键。
- 理解:同样是 Redis 4.0+ 新增的策略,适用于非常关注访问频率的场景。
allkeys-random
- 机制:从所有键中,随机淘汰某个键。
- 理解:如果你认为所有键被访问的概率都差不多,可以用这个。
no-eviction
- 机制:禁止淘汰数据。当内存不足时,所有会引起内存增加的写入命令(如
SET,LPUSH等)都会报错,读命令(GET等)可以正常执行。 - 理解:这保证了数据不会丢失,但需要上层应用处理好写入异常。适用于你把 Redis 既当缓存又当持久存储,且数据绝对不能丢失的场景。
- 机制:禁止淘汰数据。当内存不足时,所有会引起内存增加的写入命令(如
如何选择比较好的淘汰策略?
选择策略的核心原则是:根据你的数据特征和访问模式来决定。以下是一些通用的建议:
1. 首先,问自己一个问题:Redis 在你的系统中扮演什么角色?
纯缓存(Cache):数据可以从后端数据库恢复,丢失没关系。目标是提供高速访问。
- 推荐:
allkeys-lru或allkeys-lfu。 - 原因:它们能有效地根据访问模式保留热点数据,淘汰冷数据,最大化缓存命中率。
- 推荐:
持久化存储(Persistent Store):数据必须保留,不能丢失。
- 推荐:
no-eviction。 - 原因:宁可拒绝写入也要保证已有数据完整。你需要确保你的
maxmemory设置得足够大,并且有监控报警,在内存快满时及时处理(如扩容或清理数据)。
- 推荐:
2. 其次,分析你的数据访问模式
存在热点数据,访问遵循二八定律(20% 的键承担了 80% 的访问):
- 推荐:
allkeys-lru。它能非常高效地识别并保留热点数据。
- 推荐:
访问频率分布相对平均,但某些键在一段时间内被频繁访问(扫描式访问):
- 推荐:
allkeys-lfu。LFU 算法比 LRU 更能应对短期的爆发性访问,因为它关注的是频率而非最近一次访问时间。例如,一个键在短时间内被大量访问,LFU 会认为它很重要并保留,而 LRU 可能会因为它之后没被访问而将其淘汰。
- 推荐:
所有键被访问的概率几乎完全相同,毫无规律:
- 可以考虑:
allkeys-random。这是一种简单且开销低的公平策略。
- 可以考虑:
你希望通过 TTL 来精准控制数据淘汰的优先级:
- 推荐:
volatile-ttl。你希望那些即将过期的数据被优先清理掉。注意:如果你有键没设置 TTL,它们就永远不会被此策略淘汰,可能导致内存溢出。
- 推荐:
3. 考虑你的 Redis 版本
- 如果你的 Redis 是 4.0 以下的旧版本,你没有
volatile-lfu和allkeys-lfu这两个选项。 - 建议优先使用
allkeys-lru。
总结与决策流程图
你可以遵循以下流程来做出选择:
graph TD
A[开始选择] --> B{Redis的主要角色是?};
B -->|纯缓存| C{数据访问模式?};
B -->|持久化存储,数据不能丢| D[选择 no-eviction];
C -->|存在热点数据| E[选择 allkeys-lru
最通用推荐];
C -->|访问频率变化大,有爆发访问| F[选择 allkeys-lfu
(Redis 4.0+)];
C -->|所有键访问概率均等| G[选择 allkeys-random];
E --> H[完成];
F --> H;
G --> H;
D --> H;
最终建议:
对于绝大多数将 Redis 作为缓存的场景,allkeys-lru 是一个安全、高效且通用的选择,可以作为你的默认选项。如果你的访问模式更复杂且版本在 4.0 以上,可以尝试使用 allkeys-lfu 以获得更好的命中率。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 技术之路!
评论


