Redis内存回收策略

300 阅读3分钟

Redis的内存回收机制主要体现在以下两个方面:

(1) 删除到达过期时间的键对象。

(2) 内存使用达到maxmemory(最大可用内存)上限时触发内存溢出控制策略。

1.删除过期键对象

Redis所有的键都可以设置过期属性,内部保存在过期字典中。由于进

程内保存大量的键,维护每个键精准的过期删除机制会导致消耗大量的

CPU,对于单线程的Redis来说成本过高,因此Redis采用惰性删除和定时任

务删除机制实现过期键的内存回收。

(1) 惰性删除

惰性删除用于当客户端读取带有超时属性的键时,如果已经超过键设置的过期时间,会执行删除操作并返回空,这种策略是出于节省CPU成本考虑,不需要单独维护TTL链表来处理过期键的删除。但是单独用这种方式存在内存泄露的问题,当过期键一直没有访问将无法得到及时删除,从而导致内存不能及时释放。正因为如此,Redis还提供另一种定时任务删除机制作为惰性删除的补充。

(2) 定时任务删除

Redis内部维护一个定时任务,默认每秒运行10次(通过配置hz控制)。定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比例、使用快慢两种速率模式回收键。流程图如图:

流程说明:

  1. 定时任务在每个数据库空间随机检查20个键,当发现过期时删除对应的键。

  2. 如果超过检查数25%的键过期,循环执行回收逻辑直到不足25%或运行超时为止,慢模式下超时时间为25毫秒。

  3. 如果之前回收键逻辑超时,则在Redis触发内部事件之前再次以快模式运行回收过期键任务,快模式下超时时间为1毫秒且2秒内只能运行1次。

  4. 快慢两种模式内部删除逻辑相同,只是执行的超时时间不同。

2.内存溢出控制策略

当Redis所用内存达到maxmemory(最大可用内存)上限时会触发相应的溢出控制策略。具体策略受maxmemory-policy参数控制,Redis支持6种策略,如下所示:

策略说明
noeviction默认策略,不会删除任何数据,拒绝所有写入操作并返回客户端错误信息(error)OOM command not allowed when used memory,此时Redis只响应读操作
volatile-lru根据LRU算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略
allkeys-lru根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止
allkeys-random随机删除所有键,直到腾出足够空间为止
volatile-random随机删除过期键,直到腾出足够空间为止
volatile-ttl根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略

说明: LRU算法是为了找出最近未使用的键

内存溢出控制策略可以采用config set maxmemory-policy{policy}动态配置。Redis支持丰富的内存溢出应对策略,可以根据实际需求灵活定制,比如当设置volatile-lru策略时,保证具有过期属性的键可以根据LRU剔除,而未设置超时的键可以永久保留。还可以采用allkeys-lru策略把Redis变为纯缓存服务器使用。当Redis因为内存溢出删除键时,可以通过执行info stats命令查看evicted_keys指标找出当前Redis服务器已剔除的键数量。