Redis中过期键删除的三种方法

 更新时间:2024年05月19日 09:04:52   作者:物与我皆无尽也  
Redis中可以设置键的过期时间,并且通过取出过期字典(expires dict)中键的过期时间和当前时间比较来判断是否过期,那么一个过期的键是怎么被删除的呢?本文给大家总结了三种方法,选了其中两种给大家详细的介绍一下,需要的朋友可以参考下

Redis中可以设置键的过期时间,并且通过取出过期字典(expires dict)中键的过期时间和当前时间比较来判断是否过期。

那么一个过期的键是怎么被删除的呢?

定时删除

定时删除:在设置键的过期时间时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。

这是对内存最友好的,因为他通过定时器保证了过期即会删除,并释放过期键占用的内存。但是这是对CPU最不友好的,在过期键比较多的情况下,删除大量过期键会占用相当一部分CPU时间,会对服务器的的响应时间和吞吐量造成影响。

如果服务器当前不缺少内存,那么服务器应该优先将CPU时间用在处理客户端的命令请求上面,而不是用在删除过期键上面。
而且,创建一个定时器需要用到Redis服务器中的时间事件,而其实现方式是无序链表,所以查找一个事件的时间复杂度为O(N),并不能高效地处理大量时间事件。

惰性删除

惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。

惰性删除策略对CPU时间来说是最友好的:程序只会在取出键时才对键进行过期检查。但它对内存是最不友好的,如果一个键已经过期,那么只要这个过期键不被访问,它所占用的内存就不会释放。(甚至可以将这种情况看作是一种内存泄漏,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息)

定期删除

定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

定期删除策略是前两种策略的一种整合和折中,它的难点是确定删除操作执行的时长和频率:

  • 如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时
    删除策略,以至于将CPU时间过多地消耗在删除过期键上面。
  • 如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除策
    略一样,出现浪费内存的情况

因此,如果采用定期删除策略的话,服务器必须根据情况合理地设置删除操作的执行时长和执行频率。

Redis的实现

Redis 选择「惰性删除+定期删除」这两种策略配和使用

惰性删除

惰性删除策略由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令在执行之前都会调用expireIfNeeded函数对输入键进行检查:如果输人键已经过期,那么将输人键从数据库中删除;如果输人键未过期,则不做动作。

Redis 的惰性删除策略由db.c文件中的 expireIfNeeded 函数实现,代码如下:

int expireIfNeeded(redisDb *db, robj *key) {
    // 判断 key 是否过期
    if (!keyIsExpired(db,key)) 
        return 0;

    // 删除过期键 
    // 如果 server.lazyfree_lazy_expire 为 1 表示异步删除,反之同步删除;
    return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :
                                         dbSyncDelete(db,key);
}

Redis 在访问或者修改 key 之前,都会调用 expireIfNeeded 函数对其进行检查,检查 key 是否过期:

  • 如果过期,则删除该 key,至于选择异步删除,还是选择同步删除,根据 lazyfree_lazy_expire 参数配置决定(Redis 4.0版本开始提供参数),然后返回 null 客户端
  • 如果没有过期,正常处理指令

定期删除

在 Redis 中,默认每秒进行 10 次过期检查一次数据库,此配置可通过 Redis 的配置文件 redis.conf 进行配置(hz),它的默认值是10。

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

过程用伪代码表示为:

#代码来自《Redis设计与实现》,版本是Redis 2.9。跟新版redis应该有所偏差

#默认每次检查的数据库数量
DEFAULT_ DB_ NUMBERS = 16
#默认每个数据库检查的键数量
DEFAULT KEY_ NUMBERS = 20
#全局变量,记录检查进度.
current_ db = 0

def activeExpireCycle() :
    #遍历各个数据库
    for i in range (db_numbers) :
        #已经遍历一轮,将current_ db重置为0,开始新的一轮遍历
        if current_db == server.dbnum:
            current_db = 0
            
        #获取当前要处理的数据库
        redisDb = server.db[current__db]
        #将数据库索引增1,指向下一个要处理的数据库
        current_db += 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

总的来说就是,定期删除会在规定时间(时间不超过上限,25ms)内依次遍历所有数据库,对于每个数据库会依次随机获取20个键并删除过期的键,如果过期键超过25%会继续随机获取20个键。

以上就是Redis中过期键删除的三种方法的详细内容,更多关于Redis过期键删除的资料请关注脚本之家其它相关文章!

相关文章

  • 浅谈redission锁的默认失效时间

    浅谈redission锁的默认失效时间

    Redisson是一个基于Redis的Java驻留库,提供了许多分布式对象和服务,包括分布式锁,本文主要介绍了浅谈redission锁的默认失效时间, 具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Redis有序集合类型的常用命令小结

    Redis有序集合类型的常用命令小结

    这篇文章先是给大家简单介绍了一下有序集合类型,然后详细整理了关于Redis有序集合类型的常用命令,通过整理的这些命令相信会给大家的工作或学习带来一定的帮助,有需要的朋友们下面来一起看看吧。
    2016-09-09
  • Redis分布式锁的实现方式

    Redis分布式锁的实现方式

    本文主要介绍了Redis分布式锁的实现方式,分布式锁是 满足分布式系统或集群模式下多进程可见并且互斥的锁。感兴趣的同学可以参考阅读
    2023-04-04
  • redis中List列表常见命令及使用场景

    redis中List列表常见命令及使用场景

    这篇文章主要给大家介绍了关于redis中List列表常见命令及使用场景的相关资料,Redis列表是简单的字符串列表,按照插入顺序排序,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • 多维度深入分析Redis的5种基本数据结构

    多维度深入分析Redis的5种基本数据结构

    此篇文章主要对Redis的5种基本数据类型,即字符串(String)、列表(List)、散列(Hash)、集合(Set)、有序集合(Sorted Set),从使用场景和底层结构出发,进行多维度深入分析。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • Redis 对比 Memcached 并在 CentOS 下进行安装配置详解

    Redis 对比 Memcached 并在 CentOS 下进行安装配置详解

    Redis 是一个开源、支持网络、基于内存、键值对的 Key-Value 数据库,本篇文章主要介绍了Redis 对比 Memcached 并在 CentOS 下进行安装配置详解,有兴趣的可以了解一下。
    2016-11-11
  • Redis客户端连接远程Redis服务器方式

    Redis客户端连接远程Redis服务器方式

    这篇文章主要介绍了Redis客户端连接远程Redis服务器方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • springboot中操作redis实例分享

    springboot中操作redis实例分享

    本文介绍了如何在Spring Boot应用中整合Redis缓存技术,包括配置Redis连接、定义Redis模板、实现Redis的基本操作以及使用Spring Cache注解。这些内容可帮助开发者快速掌握Spring Boot与Redis的集成,并提高应用性能。
    2023-06-06
  • Redis都做了哪些加快速度的设计

    Redis都做了哪些加快速度的设计

    这篇文章主要介绍了Redis都做了哪些加快速度的设计的相关资料,需要的朋友可以参考下
    2021-02-02
  • 本地访问不到公网redis的解决方案

    本地访问不到公网redis的解决方案

    本文详述了本地访问不到公网redis的解决方案,包括分析报错原因、Redis配置文件的区别、bind和protected-mode配置的解析,最终通过修改Redis配置文件及创建启动脚本解决了访问不到公网redis得问题,需要的朋友可以参考下
    2024-08-08

最新评论