Redis过期删除策略


最近线上遇到Redis内存达到maxmemory限制后,数据淘汰过慢导致拖慢应用请求的问题。后来仔细看了一下Redis的各种数据淘汰策略,总结一下。

首先,Redis有三种删除key的时机,它们对应不同的淘汰策略:

1. 当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key。

2. 由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key。

3. 当前已用内存超过maxmemory限定时,触发主动清理策略。

下面详细说一下定期主动淘汰策略和主动清理策略,以及它们所对应的配置参数的含义。

• 定期主动淘汰策略

首先,这里的“定期”指的是Redis定期调用databasesCron()函数时触发的清理策略,这个定期的频率由配置文件中的hz参数决定,代表了一秒钟内,后台任务期望被调用的次数。Redis-3.0.0中的默认值是10,代表每秒钟调用10次后台任务。

hz调大将会提高Redis主动淘汰的频率,如果你的Redis存储中包含很多冷数据占用内存过大的话,可以考虑将这个值调大,但Redis作者建议这个值不要超过100。我们实际线上将这个值调大到100,观察到CPU会增加2%左右,但对冷数据的内存释放速度确实有明显的提高(通过观察keyspace个数和used_memory大小)。

除了主动淘汰的频率外,Redis对每次淘汰任务执行的最大时长也有一个限定,这样保证了每次主动淘汰不会过多阻塞应用请求,以下是这个限定计算公式:

#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */

...

timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;

可以看出timelimit和server.hz是一个倒数的关系,也就是说hz配置越大,timelimit就越小。换句话说是每秒钟期望的主动淘汰频率越高,则每次淘汰最长占用时间就越短。这里每秒钟的最长淘汰占用时间是固定的250ms(1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/100),而淘汰频率和每次淘汰的最长时间是通过hz参数控制的。

具体的淘汰过程为:在redis.c/activeExpireCycle()函数中,针对每个db有一个循环,每次从db->expires集合中随机取出20个key,如果有超过5个key过期淘汰,则继续循环。也就是说如果超过25%的key过期淘汰,则继续淘汰,直到随机抽取的key的过期率低于25%,或者整个循环时间超过timelimit的最大限定。则结束整个淘汰过程。

从以上的分析看,当redis中的过期key比率没有超过25%之前,提高hz可以明显提高扫描key的最小个数。假设hz为10,则一秒内最少扫描200个key(一秒调用10次*每次最少随机取出20个key),如果hz改为100,则一秒内最少扫描2000个key;另一方面,如果过期key比率超过25%,则扫描key的个数无上限,但是cpu时间每秒钟最多占用250ms。

• maxmemory的主动清理策略

当mem_used内存已经超过maxmemory的设定,对于所有的读写请求,都会触发redis.c/freeMemoryIfNeeded(void)函数以清理超出的内存。注意这个清理过程是阻塞的,直到清理出足够的内存空间。所以如果在达到maxmemory并且调用方还在不断写入的情况下,可能会反复触发主动清理策略,导致请求会有一定的延迟。

清理时会根据用户配置的maxmemory-policy来做适当的清理(一般是LRU或TTL),这里的LRU或TTL策略并不是针对redis的所有key,而是以配置文件中的maxmemory-samples个key作为样本池进行抽样清理。

maxmemory-samples在redis-3.0.0中的默认配置为5,如果增加,会提高LRU或TTL的精准度,redis作者测试的结果是当这个配置为10时已经非常接近全量LRU的精准度了,并且增加maxmemory-samples会导致在主动清理时消耗更多的CPU时间。

建议:

尽量不要触发maxmemory,最好在mem_used内存占用达到maxmemory的一定比例后,需要考虑调大hz以加快淘汰,或者进行集群扩容。

如果能够控制住内存,则可以不用修改maxmemory-samples配置;如果Redis本身就作为LRU cache服务(这种服务一般长时间处于maxmemory状态,由Redis自动做LRU淘汰),可以适当调大maxmemory-samples。

下面关于Redis的文章您也可能喜欢,不妨参考下:

Ubuntu 14.04下Redis安装及简单测试

Redis主从复制基本配置

Redis集群明细文档

Ubuntu 12.10下安装Redis(图文详解)+ Jedis连接Redis

Redis系列-安装部署维护篇

CentOS 6.3安装Redis

Redis安装部署学习笔记

Redis配置文件redis.conf 详解

Redis 的详细介绍:请点这里
Redis 的下载地址:请点这里

本文永久更新链接地址

相关内容