广告位联系
返回顶部
分享到

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

Redis 来源:互联网 作者:佚名 发布时间:2024-05-19 10:23:28 人浏览
摘要

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 函数实现,代码如下:

1

2

3

4

5

6

7

8

9

10

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)中随机检查一部分键的过期时间,并删除其中的过期键。

过程用伪代码表示为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

#代码来自《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个键。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • redis淘汰策略的几种实现介绍
    redis内存数据数据集大小升到一定大的时候,就会实行数据淘汰策略(回收策略)。 1,volatile-lru:从已设置过期时间的哈希表(server.db[i].e
  • Redis中过期键删除的三种方法

    Redis中过期键删除的三种方法
    Redis中可以设置键的过期时间,并且通过取出过期字典(expires dict)中键的过期时间和当前时间比较来判断是否过期。 那么一个过期的键是
  • redis并发之跳表的实现
    跳表(Skip List)是一种用于实现有序集合(Sorted Set)的数据结构,在 Redis 中被广泛应用。跳表的设计旨在提供高效的有序集合操作,可以将
  • 保证Redis中存储的Token安全性的介绍
    确保Redis中存储的Token安全性是一个多层面的任务,涉及到网络、应用、数据和操作等多个方面的安全措施。以下是一些更详细的实践建议和
  • redis和redisson实现分布式锁的操作方法介绍

    redis和redisson实现分布式锁的操作方法介绍
    基于setnx命令的分布式锁 1. 加锁 使用 Redis 实现分布式锁,最直接的想法是利用 setnx 和 expire 命令实现加锁。 在 Redis 中,setnx 是「set if no
  • Redisson分布式限流的实现原理介绍

    Redisson分布式限流的实现原理介绍
    我们目前在工作中遇到一个性能问题,我们有个定时任务需要处理大量的数据,为了提升吞吐量,所以部署了很多台机器,但这个任务在运
  • 宝塔中ThinkPHP框架使用Redis的一系列教程介绍

    宝塔中ThinkPHP框架使用Redis的一系列教程介绍
    Redis是一种常用的非关系型数据库,主要用作数据缓存,数据保存形式为key-value,键值相互映射。它的数据存储跟MySQL不同,它数据存储在内存之中
  • Redisson如何解决redis分布式锁过期时间到了业务没

    Redisson如何解决redis分布式锁过期时间到了业务没
    Redis锁的过期时间小于业务的执行时间该如何续期? 问题分析 首先如果你之前用Redis的分布式锁的姿势正确,并且看过相应的官方文档的话
  • 宝塔中ThinkPHP框架使用Redis的教程

    宝塔中ThinkPHP框架使用Redis的教程
    Redis是一种常用的非关系型数据库,主要用作数据缓存,数据保存形式为key-value,键值相互映射。它的数据存储跟MySQL不同,它数据存储在内存之中
  • Redis使用Bitmap的方法实现

    Redis使用Bitmap的方法实现
    1. Bitmap 是什么 Bitmap(也称为位数组或者位向量等)是一种实现对位的操作的数据结构,在数据结构加引号主要因为: Bitmap 本身不是一种数据
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计