Redis 的过期策略和淘汰策略是内存管理的核心机制,分别用于处理键的自动失效和内存不足时的数据清理。以下是详细说明:
1 、过期删除策略(Expiration Policy)
处理已设置过期时间(EXPIRE
)的键,确保它们在过期后被删除。
1.1 被动删除(惰性删除)
- 默认行为:始终启用,无需配置。
- 触发时机:当客户端尝试访问某个键时,Redis 会检查其是否过期。
- 行为:若键已过期,则直接删除并返回空结果,不返回数据。
- 优点:仅在访问时检查,节省 CPU 资源。
- 缺点:长期未被访问的过期键可能残留内存(需配合定期删除)。
1.2 定期删除(主动扫描)
- 默认行为:始终启用,无需配置。
- 触发时机:Redis 默认每秒 10 次随机抽查部分键。
- 行为:
- 随机抽取 20 个设置了过期时间的键。
- 删除其中已过期的键。
- 若本轮删除的键超过 25%,重复流程(避免阻塞)。
- 配置参数:
hz 10
:控制定期删除的频率(默认每秒 10 次)。active-expire-effort
:调整扫描强度(1-10,值越大越严格)。
- 优点:平衡内存和性能,避免内存泄漏。
- 缺点:无法保证及时删除所有过期键。
1.3. 过期键的存储
- Redis 使用独立的字典(
expires
)记录键的过期时间,与主键字典分离。 - 删除过期键时,会同时从主字典和
expires
字典中移除。
2 淘汰删除策略(Eviction Policy)
当内存达到 maxmemory
限制时,根据策略主动删除键以释放空间。
2.1 不淘汰(noeviction)
- 行为:内存不足时,拒绝写入操作(返回错误),但允许读取和删除。
- 适用场景:数据重要性高,不允许丢失(如分布式锁)。
2.2 LRU 策略(Least Recently Used)
- allkeys-lru:从所有键中淘汰最久未使用的键。
- volatile-lru:仅从设置了过期时间的键中淘汰最久未使用的键。
- 实现:Redis 使用近似 LRU 算法,维护一个随机采样的候选池(默认 5 个样本,可通过
maxmemory-samples
调整)。
2.3 LFU 策略(Least Frequently Used,Redis 4.0+)
- allkeys-lfu:从所有键中淘汰访问频率最低的键。
- volatile-lfu:仅从设置了过期时间的键中淘汰访问频率最低的键。
- 实现:记录键的访问次数和衰减因子,优先淘汰冷数据。
2.4 随机策略
- allkeys-random:从所有键中随机淘汰。
- volatile-random:仅从设置了过期时间的键中随机淘汰。
- 适用场景:数据无明显访问模式,需快速释放内存。
2.5 TTL 策略
- volatile-ttl:仅淘汰设置了过期时间的键中,剩余生存时间(TTL)最短的键。
- 适用场景:希望优先保留长期有效的数据。
2.6 策略对比与选择建议
策略 | 适用场景 | 特点 |
---|---|---|
noeviction | 禁止数据丢失(如缓存+数据库模式) | 内存不足时阻塞写入 |
allkeys-lru | 缓存场景,数据访问模式符合局部性 | 高效利用内存,推荐默认策略 |
volatile-lru | 需结合过期时间使用 | 仅淘汰带过期时间的键 |
allkeys-lfu | 访问频率差异大的数据 | 适合热点数据频繁访问的场景 |
volatile-ttl | 希望短期数据优先淘汰 | 简单直接,但可能误删热点数据 |
2.7 最佳实践
- 缓存场景:
- 优先使用
allkeys-lru
或allkeys-lfu
,结合maxmemory-policy
配置。 - 设置合理的
maxmemory
(如系统内存的 60%-80%)。
- 优先使用
- 持久化数据:
- 使用
noeviction
,配合数据库做主从备份。
- 使用
- 混合场景:
- 结合
volatile-ttl
或volatile-lru
,为部分键设置过期时间。
- 结合
2.8 淘汰策略的其它问题
2.8.1 数据库有1000万数据,Redis只能缓存20w数据,如何保证Redis中的数据都是热点数据 ?
使用allkeys-lru(挑选最近最少使用的数据淘汰)淘汰策略,留下来的都是经常访问的热点数据
2.8.2 Redis的内存用完了会发生什么?
主要看数据淘汰策略是什么?如果是默认的配置( noeviction ),会直接报错