关于Redis的数据清理

我们数据平台中有使用Redis来给线上提供低延时(20毫秒以内)的高并发读写请求,其中最大的Redis使用了阿里云的Redis集群(256G),存储的记录超过10亿,Key的有效期设置为15天,每天写入的记录大概5000万左右,QPS大概在6万左右。由于过期Key的产生速度大于Redis自动清理的速度,因此在Redis中会有大量过期Key未被及时清理。

为什么有过期的Key未被清理呢?这个得先熟悉一下Redis的删除策略。

Redis常用的删除策略有以下三种:

  • 被动删除(惰性删除):当读/写一个已经过期的Key时,会触发惰性删除策略,直接删除掉这个Key;
  • 主动删除(定期删除):Redis会定期巡检,来清理过期Key;
  • 当内存达到maxmemory配置时候,会触发Key的删除操作;

另外,还有一种基于触发器的删除策略,因为对Redis压力太大,一般没人使用。

这里先介绍后两种删除策略(网上有很多说明)。

主动删除(定期删除)

在 Redis 中,常规操作由 redis.c/serverCron 实现,它主要执行以下操作:

  • 更新服务器的各类统计信息,比如时间、内存占用、数据库占用情况等。
  • 清理数据库中的过期键值对。
  • 对不合理的数据库进行大小调整。
  • 关闭和清理连接失效的客户端。
  • 尝试进行 AOF 或 RDB 持久化操作。
  • 如果服务器是主节点的话,对附属节点进行定期同步。
  • 如果处于集群模式的话,对集群进行定期同步和连接测试。

Redis 将 serverCron 作为时间事件来运行,从而确保它每隔一段时间就会自动运行一次, 又因为 serverCron 需要在 Redis 服务器运行期间一直定期运行, 所以它是一个循环时间事件:serverCron 会一直定期执行,直到服务器关闭为止。

在 Redis 2.6 版本中, 程序规定 serverCron 每秒运行 10 次, 平均每 100 毫秒运行一次。 从 Redis 2.8 开始, 用户可以通过修改 hz选项来调整 serverCron 的每秒执行次数, 具体信息请参考 redis.conf 文件中关于 hz 选项的说明。

也叫定时删除,这里的“定期”指的是Redis定期触发的清理策略,由位于src/redis.c的activeExpireCycle(void)函数来完成。

serverCron是由redis的事件框架驱动的定位任务,这个定时任务中会调用activeExpireCycle函数,针对每个db在限制的时间REDIS_EXPIRELOOKUPS_TIME_LIMIT内迟可能多的删除过期key,之所以要限制时间是为了防止过长时间 的阻塞影响redis的正常运行。这种主动删除策略弥补了被动删除策略在内存上的不友好。

因此,Redis会周期性的随机测试一批设置了过期时间的key并进行处理。测试到的已过期的key将被删除。典型的方式为,Redis每秒做10次如下的步骤:

  • 随机测试100个设置了过期时间的key
  • 删除所有发现的已过期的key
  • 若删除的key超过25个则重复步骤1

这是一个基于概率的简单算法,基本的假设是抽出的样本能够代表整个key空间,redis持续清理过期的数据直至将要过期的key的百分比降到了25%以下。这也意味着在任何给定的时刻已经过期但仍占据着内存空间的key的量最多为每秒的写操作量除以4.

Redis-3.0.0中的默认值是10,代表每秒钟调用10次后台任务。

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


  1. #define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */  
  2. …  
  3. timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100; 

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

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

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

当REDIS运行在主从模式时,只有主结点才会执行上述这两种过期删除策略,然后把删除操作”del key”同步到从结点。

maxmemory

当前已用内存超过maxmemory限定时,触发主动清理策略,这些策略可以配置(参数maxmemory-policy),包括以下几个:

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

no-enviction(驱逐):禁止驱逐数据

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

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

总结与备忘

如果Redis中每天过期大量Key(比如几千万),那么必须得考虑过期Key的清理:

增加Redis主动清理的频率(通过调大hz参数);

手动清理过期Key,最简单的方法是进行scan操作,scan操作会触发第一种被动删除,scan操作时候别忘了加count;

dbsize命令返回的Key数量,包含了过期Key;

randomkey命令返回的Key,不包含过期Key;

scan命令返回的Key,包含过期Key;

info命令返回的# Keyspace:

db6:keys=1034937352,expires=994731489,avg_ttl=507838502

keys对应的Key数量等同于dbsize;

expires指的是设置了过期时间的Key数量;

avg_ttl指设置了过期时间的Key的平均过期时间(单位:毫秒);

本文作者:佚名

来源:51CTO

时间: 2024-11-03 10:56:33

关于Redis的数据清理的相关文章

数据同步-redis 删除数据并保存

问题描述 redis 删除数据并保存 30C Redis怎么删除一个月前的数据,并把这些数据保存到MySQL, 解决方案 http://www.kuqin.com/shuoit/20140411/339149.html 解决方案二: http://blog.csdn.net/caishenfans/article/details/44902651 解决方案三: 关键是你要获取i 个月前的数据,这个你保存的时候如果有设置i一个时间字段,就可以排序取出来,然后插入mysql,然后删除del 解决方案

自定义-flume怎么从redis读取数据,sink的时候怎么按照我自己的规则格式保存日志

问题描述 flume怎么从redis读取数据,sink的时候怎么按照我自己的规则格式保存日志 如题 flume要从redis读取数据要自定义source吗?自定义source应该怎么写?

介绍一款数据清理,数据重构软件--TIBCO CLARITY

问题描述 TibcoClarity是tibco公司一款数据清理,重构,整合的工具.它基于Google的OpenRefine开发,加入了多种商业软件(如Salesforce,Maketo)和数据库的整合,添加了地址校验,数据类型校验等功能TIBCOClarity–CloudEditionenablesbusinessuserstodiscover,profile,cleanse,andstandardizerawdatacollatedfromdisparatesourcesandprovideg

redis储存数据的地方?

问题描述 redis储存数据的地方? 最近在进行redis的学习,有几个问题的不是很明白 1.redis的保存数据是在内存中还是在磁盘中. 2.如果是保存在内存中,但内存满了怎么办,或者机器宕机怎么办? 3.我使用的是java语言,java提供的jedis包中提供的方法,用来保存数据的话,数据是写入哪里?内存还是磁盘 解决方案 数据在内存中.不过也能保存到文件.有rdb格式文件. 内存满了,redis会清除数据. 缺省写入内存.不过也可以要求同时保存到文件

java实现数据备份和数据清理

问题描述 求用java实现的数据备份和数据清理完整代码? 解决方案 解决方案二:可以通过调用(远程)数据库的命令执行,处理数据命令执行的结果,比如数据库备份产生的文件期待更好的思路...解决方案三:劝你不要用Java来做这种系统管理方面的工作.解决方案四:该回复于2011-03-10 09:24:08被版主删除解决方案五:你这个问题没有说清楚啊?数据备份的数据源是什么?数据库?xml文件?excel文件?是否需要远程操作?解决方案六:谢谢各位啦!我是个大菜鸟,不懂!备份的数据库是sqlserve

spring + redis 实现数据的缓存

1.实现目标 通过redis缓存数据.(目的不是加快查询的速度,而是减少数据库的负担) 2.所需jar包 注意:jdies和commons-pool两个jar的版本是有对应关系的,注意引入jar包是要配对使用,否则将会报错.因为commons-pooljar的目录根据版本的变化,目录结构会变.前面的版本是org.apache.pool,而后面的版本是org.apache.pool2... style=" color: white; font-size: 17px; font-weight: bo

唐福林:新浪微博的Redis大数据之路

本文讲的是唐福林:新浪微博的Redis大数据之路,2012年4月15日消息,由IT168(ITPUB.IXPUB.ChinaUnix)主办的2012中国数据库技术大会(DTCC)进入第三天的议程.大会针对大数据架构设计.数据库安全.分布式数据库.商业智能.NoSQL.Hadoop等多个重点话题进行深入探讨.此次大会得到了全国数据库技术高手们的高度关注与支持,是当前象征最高技术水平的数据库工程师盛会. 在今天下午进行的"NoSQL数据库创新专场"中,新浪微博开放平台资深工程师唐福林发表主

大数据清理软件公司Trifacta融资3500万美元

Trifacta 是一家提供大数据清理软件服务的创业公司,公司刚获得一轮 3500 万美元的融资.Cathay Innovation.Accel Partners.Greylock Partners 和 Ignition Partners 都参与了本轮融资.到目前为止,公司的融资总额已达 7600 万美元.公司主要利用这轮融资进一步拓展公司业务. 一直以来,杂乱的.非结构化的数据都是企业数据治理的心腹之患.尽管许多企业竭尽所能保留下来了各种客户.内部流程及运营方面的数据,但是将这些裸数据变成可供

MySQL数据清理的需求分析和改进

昨天帮一个朋友看了MySQL数据清理的问题,感觉比较有意思,具体的实施这位朋友还在做,已经差不多了,我就发出来大家一起参考借鉴下. 为了保证信息的敏感,里面的问题描述可能和真实情况不符,但是问题的处理方式是真实的. 首先这位朋友在昨天下午反馈说他有一个表大小是近600G,现在需要清理数据,只保留近几个月的数据.按照这个量级,我发现这个问题应该不是很好解决,得非常谨慎才对.如果是通用的思路和方法,我建议是使用冷热数据分离的方式.大体有下面的几类玩法: exchange partition,这是亮点