上一篇我们深度拆解了Redis缓存、队列、计数器三大核心场景,讲透了Redis成为后端刚需中间件的核心价值。在实际生产使用中,我们会给缓存、计数器等数据设置过期时间,也会遇到内存占用超限的问题,一旦处理不当,就会出现脏数据堆积、内存溢出、服务卡顿等严重故障。

这就离不开Redis的两大核心保障机制:过期策略内存淘汰机制。前者负责清理过期数据,释放无效内存;后者负责在内存耗尽前主动清理数据,防止服务崩溃。本篇就从原理、实现、选型、实操四个维度,彻底讲透这两大机制,帮你精准配置,守住Redis内存底线。

核心警示:过期策略负责“该删的数据及时删”,内存淘汰负责“内存不够时主动删”,二者配合才能保证Redis长期稳定运行,缺一不可。

一、Redis过期键:数据是怎么被标记过期的?

Redis会给每个设置了过期时间的Key,维护一个过期字典(本质是哈希表),字典里存储Key的指针和对应的过期时间戳(毫秒级)。

  • 设置过期命令:EXPIRE key secondsPEXPIRE key millisecondsSET key value EX seconds
  • 查看剩余过期时间:TTL key(返回秒数)、PTTL key(返回毫秒数)
  • 取消过期时间:PERSIST key

简单来说,Redis只会记录“哪个Key什么时候过期”,但不会到点就立刻删除,而是通过过期策略来批量清理,这也是Redis高性能的关键设计。


二、Redis过期策略:三种方案对比,生产用哪种?

Redis并没有采用“定时立即删除”这种简单粗暴的方式,而是结合了惰性删除定期删除两种策略,兼顾内存回收效率和CPU性能损耗。

1. 定时删除(Redis不采用)

原理:给每个过期Key创建定时器,到达过期时间立刻删除。

  • 优点:内存回收及时,不会浪费内存
  • 缺点:大量定时器会占用CPU资源,高并发场景下CPU优先处理命令,会严重拖累性能
  • 结论:对CPU不友好,Redis弃用

2. 惰性删除(Redis默认采用)

原理:不主动删除过期Key,等到客户端请求查询这个Key时,才判断是否过期,过期则删除并返回空。

  • 优点:对CPU最友好,只在查询时做判断,不占用额外资源
  • 缺点:如果过期Key一直不被访问,会永久占用内存,造成内存泄漏
  • 适用场景:冷门、不常访问的过期数据

3. 定期删除(Redis默认采用)

原理:每隔一段时间(默认100ms),随机抽取一部分设置了过期时间的Key,检查是否过期,过期则删除。

  • 优点:控制CPU损耗,同时批量清理过期Key,平衡内存和CPU资源
  • 缺点:随机抽取存在局限性,无法保证所有过期Key都被清理
  • 核心参数(redis.conf配置):hz 10(每秒执行10次定期删除,即每100ms一次)

4. 生产默认策略:惰性删除+定期删除结合

Redis采用惰性删除+定期删除的组合方案,取长补短:

  • 日常查询触发惰性删除,及时清理访问到的过期Key
  • 定期删除兜底,清理长期不访问的过期Key,防止内存堆积

即便如此,仍有少量过期Key无法被及时清理,如果此时Redis内存占用达到上限,就需要内存淘汰机制来兜底。


三、Redis内存淘汰机制:8种策略全解析

当Redis内存使用量达到配置的maxmemory上限时,会触发内存淘汰机制,根据指定策略删除部分Key,为新数据腾出空间。

1. 前置配置:开启内存淘汰

先在redis.conf中配置最大内存和淘汰策略,生产环境必配:

# 配置Redis最大使用内存(建议不超过物理内存70%)
maxmemory 8gb
# 配置内存淘汰策略
maxmemory-policy allkeys-lru

2. 8种内存淘汰策略详解

Redis 6.0+提供8种淘汰策略,分为不淘汰仅淘汰过期Key淘汰所有Key三大类:

策略类型策略名称核心逻辑适用场景
不淘汰(默认)noeviction内存满后拒绝写入新数据,返回错误,不删除任何Key严禁数据丢失的场景,生产禁用
仅淘汰过期Key(volatile-前缀)volatile-lru淘汰过期Key中最少使用(LRU)的Key部分数据永久有效,部分数据过期
volatile-lfu淘汰过期Key中使用频率最低(LFU)的Key需要按访问频率淘汰的场景
volatile-random过期Key中随机淘汰无热点数据,数据访问均匀
volatile-ttl淘汰过期Key中即将过期(TTL最小)的Key需要保留近期过期数据的场景
淘汰所有Key(allkeys-前缀)allkeys-lru淘汰所有Key中最少使用(LRU)的Key生产首选,热点数据缓存场景
allkeys-lfu淘汰所有Key中使用频率最低(LFU)的Key存在偶发热点,需保留高频数据
allkeys-random所有Key中随机淘汰数据访问频率均匀,无明显热点

3. 核心概念:LRU vs LFU

  • LRU(最近最少使用):优先删除很久没访问的数据,适合热点数据缓存场景
  • LFU(最少使用频率):优先删除访问次数最少的数据,适合避免偶发热点占用内存的场景

四、生产环境选型推荐:怎么配置最稳妥?

1. 淘汰策略首选:allkeys-lru

绝大多数业务(尤其是缓存场景)推荐使用allkeys-lru,理由:

  • 自动保留热点数据,清理冷门数据,缓存命中率最高
  • 无需区分过期Key和永久Key,适配绝大多数场景
  • 性能稳定,不会出现随机删除导致的业务波动

2. 特殊场景选型

  • 业务有严格永久数据+过期数据区分:选volatile-lru
  • 存在偶发批量热点,避免内存被占用:选allkeys-lfu
  • 数据访问完全均匀,无热点:选allkeys-random

3. 避坑禁忌

  • ❌ 生产环境严禁使用noeviction,内存满后直接拒绝写入,导致业务瘫痪
  • ❌ 不要用volatile-random/volatile-ttl作为默认策略,清理随机性强,易丢核心数据

五、常见问题与排查

1. 明明设置了过期时间,Key却没被删除?

  • 原因:惰性删除未触发,定期删除没抽到该Key,属于正常现象
  • 解决:内存达到maxmemory后,淘汰机制会清理;或手动执行命令删除

2. Redis内存持续上涨,淘汰策略不生效?

  • 原因:maxmemory设置过大,或淘汰策略配置错误;存在大量BigKey占用内存
  • 解决:核对配置参数,清理BigKey,调小maxmemory

3. 缓存命中率突然下降?

  • 原因:淘汰策略不合理,热点数据被误删;定期删除频率过高
  • 解决:改用allkeys-lru策略,优化hz参数(默认10即可,不建议随意调大)

排查口诀:过期靠懒删+定期删兜底,内存靠淘汰策略护航,配置不对全白费,选对LRU最稳妥。


六、总结与实操建议

Redis过期策略内存淘汰机制是保障内存安全的两道防线:

  • 过期策略:惰性删除+定期删除组合,清理无效过期数据,节省内存
  • 内存淘汰:内存超限后主动删数据,allkeys-lru是生产万能选型

生产实操步骤

  1. 设置maxmemory为物理内存的70%左右,预留内存空间
  2. 配置maxmemory-policy为allkeys-lru
  3. 保持默认hz=10,不随意修改定期删除频率
  4. 定期监控内存使用率、淘汰次数、缓存命中率

发表回复