Redis中可以设置键的过期时间,并且通过取出过期字典(expires dict)中键的过期时间和当前时间比较来判断是否过期。 那么一个过期的键是怎么被删除的呢? 定时删除 定时删除:在设置键的过
Redis中可以设置键的过期时间,并且通过取出过期字典(expires dict)中键的过期时间和当前时间比较来判断是否过期。 那么一个过期的键是怎么被删除的呢? 定时删除定时删除:在设置键的过期时间时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。 这是对内存最友好的,因为他通过定时器保证了过期即会删除,并释放过期键占用的内存。但是这是对CPU最不友好的,在过期键比较多的情况下,删除大量过期键会占用相当一部分CPU时间,会对服务器的的响应时间和吞吐量造成影响。 如果服务器当前不缺少内存,那么服务器应该优先将CPU时间用在处理客户端的命令请求上面,而不是用在删除过期键上面。 惰性删除惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。 惰性删除策略对CPU时间来说是最友好的:程序只会在取出键时才对键进行过期检查。但它对内存是最不友好的,如果一个键已经过期,那么只要这个过期键不被访问,它所占用的内存就不会释放。(甚至可以将这种情况看作是一种内存泄漏,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息) 定期删除定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。 定期删除策略是前两种策略的一种整合和折中,它的难点是确定删除操作执行的时长和频率:
因此,如果采用定期删除策略的话,服务器必须根据情况合理地设置删除操作的执行时长和执行频率。 Redis的实现Redis 选择「惰性删除+定期删除」这两种策略配和使用 惰性删除惰性删除策略由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令在执行之前都会调用expireIfNeeded函数对输入键进行检查:如果输人键已经过期,那么将输人键从数据库中删除;如果输人键未过期,则不做动作。 Redis 的惰性删除策略由db.c文件中的 expireIfNeeded 函数实现,代码如下:
Redis 在访问或者修改 key 之前,都会调用 expireIfNeeded 函数对其进行检查,检查 key 是否过期:
定期删除在 Redis 中,默认每秒进行 10 次过期检查一次数据库,此配置可通过 Redis 的配置文件 redis.conf 进行配置(hz),它的默认值是10。 过期键的定期删除策略由redis.c/activeExpireCycle函数实现,每当Redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的过期字典(expires dict)中随机检查一部分键的过期时间,并删除其中的过期键。 过程用伪代码表示为:
总的来说就是,定期删除会在规定时间(时间不超过上限,25ms)内依次遍历所有数据库,对于每个数据库会依次随机获取20个键并删除过期的键,如果过期键超过25%会继续随机获取20个键。 |
2021-04-08
2021-10-03
2021-07-26
2019-10-11
2022-08-27