Redis过期键删除策略

作者: 罗曼蒂克 | 来源:发表于2017-03-04 22:42 被阅读1293次

有没有想过Redis中过期的那些键去哪了?
是谁在什么时候怎么删掉的?

先来介绍一下各种方案:


  • 定时删除: 在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作. 即从设置key的Expire开始,就启动一个定时器,到时间就删除该key;这样会对内存比较友好,但浪费CPU资源

  • 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。 即平时不处理,在使用的时候,先检查该key是否已过期,已过期则删除,否则不做处理;这样对CPU友好,但是浪费内存资源,并且如果一个key不再使用,那么它会一直存在于内存中,造成浪费

  • 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。 即设置一个定时任务,比如10分钟删除一次过期的key;间隔小则占用CPU,间隔大则浪费内存

在这三种策略中,第一种和第三种为主动删除策略,而第二种则为被动删除策略。

Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。


惰性删除策略的实现

过期键的惰性删除策略由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令在执行之前都会调用expireIfNeeded函数对输入键进行检查:

  • 如果输入键已经过期,那么expireIfNeeded函数将输入键从数据库中删除。
  • 如果输入键未过期,那么expireIfNeeded函数不做动作。

expireIfNeeded函数就像一个过滤器,它可以在命令真正执行之前,过滤掉过期的输入键,从而避免命令接触到过期键。

另外,因为每个被访问的键都可能因为过期而被expireIfNeeded函数删除,所以每个命令的实现函数都必须能同时处理键存在以及键不存在这两种情况:

  • 当键存在时,命令按照键存在的情况执行。
  • 当键不存在或者键因为过期而被expireIfNeeded函数删除时,命令按照键不存在的情况执行。

举个例子,下图展示了GET命令的执行过程,在这个执行过程中,命令需要判断键是否存在以及键是否过期,然后根据判断来执行合适的动作。

定期删除策略的实现

过期键的定期删除策略由redis.c/activeExpireCycle函数实现,每当Redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。

`

DEFAULT_DB_NUMBERS = 16  //默认每次检查的数据库数量
DEFAULT_KEY_NUMBERS = 20 //默认每个数据库检查的键数量
current_db = 0 //全局变量,记录检查进度
//以实际数据库数量为准
if server.dbnum < DEFAULT_DB_NUMBERS:
   db_numbers = server.dbnum
else:
   db_numbers = DEFAULT_DB_NUMBERS 
//遍历各个数据库
for i in range(db_numbers): 
    if current_db == server.dbnum://如果current_db的值等于服务器的数据库数量,
        current_db = 0 //这表示检查程序已经遍历了服务器的所有数据库一次,将current_db重置为0,开始新的一轮遍历
    redisDb = server.db[current_db] //获取当前要处理的数据库
    current_db += 1 //将数据库索引增1,指向下一个要处理的数据库
    for j in range(DEFAULT_KEY_NUMBERS): 
        if redisDb.expires.size() == 0: break //如果数据库中没有一个键带有过期时间,那么跳过这个数据库
        key_with_ttl = redisDb.expires.get_random_key() //随机获取一个带有过期时间的键
        if is_expired(key_with_ttl)://检查键是否过期,如果过期就删除它
            delete_key(key_with_ttl) 
        if reach_time_limit(): return//已达到时间上限,停止处理

`

activeExpireCycle函数的工作模式可以总结如下:

  • 函数每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键。

  • 全局变量current_db会记录当前activeExpireCycle函数检查的进度,并在下一次activeExpireCycle函数调用时,接着上一次的进度进行处理。比如说,如果当前activeExpireCycle函数在遍历10号数据库时返回了,那么下次activeExpireCycle函数执行时,将从11号数据库开始查找并删除过期键。

  • 随着activeExpireCycle函数的不断执行,服务器中的所有数据库都会被检查一遍,这时函数将current_db变量重置为0,然后再次开始新一轮的检查工作。

本文参考自 《Redis设计与实现》

相关文章

  • redis--数据库

    数据库对象定义如下: redisDb定义如下: 过期键删除 惰性删除redis过期键惰性删除策略定义在db.c/e...

  • Redis 过期策略

    redis 过期策略 redis 过期策略是:定期删除+惰性删除。 所谓定期删除,指的是 redis 默认是每隔 ...

  • Redis中Key的过期策略和淘汰机制

    Key的过期策略 Redis的Key有3种过期删除策略,具体如下: 1. 定时删除 原理:在设置键的过期时间的同时...

  • redis 过期键的删除策略

    redis 删除过期键策略  定时删除:   优点:定时删除策略对内存是最友好的:通过定时器,定时删除策略可以保证...

  • Redis单机数据库的实现

    数据库 redis默认会创建16个数据库;删除过期键有三种策略: 定时删除:对某个键设置过期时间,时间一到就删除键...

  • Redis过期删除策略和内存淘汰策略

    1. 过期删除策略 Redis可以用使用expire指令设置过期时间,在Redis内部,每当我们设置一个键的过期时...

  • Redis之内存淘汰与键过期删除策略

    键过期删除策略 Redis的键可以设置过期时间,时间一到,就会自动删除。但是我们会不会这么一种情景发生:会不会因为...

  • Redis对于过期键清除策略

    Redis对于过期键有三种清除策略: 1. 被动删除当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉...

  • redis数据淘汰机制

    redis的过期策略 redis有两种过期策略,定期删除和惰性删除 定期删除:redis每个100ms随机抽取一些...

  • redis过期数据删除策略

    过期数据删除策略  redis的过期数据删除策略使用了惰性删除和定期删除两种策略: 惰性删除发生在redis处理读...

网友评论

    本文标题:Redis过期键删除策略

    本文链接:https://www.haomeiwen.com/subject/uonjgttx.html