服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Redis - 浅谈redis的过期时间设置和过期删除机制

浅谈redis的过期时间设置和过期删除机制

2022-10-10 17:19梦里寻乡 Redis

本文主要介绍了redis的过期时间设置和过期删除机制,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

一:设置过期时间

redis有四种命令可以用于设置键的生存时间和过期时间:

  • EXPIRE <KEY> <TTL> : 将键的生存时间设为 ttl 秒
  • PEXPIRE <KEY> <TTL> :将键的生存时间设为 ttl 毫秒
  • EXPIREAT <KEY> <timestamp> :将键的过期时间设为 timestamp 所指定的秒数时间戳
  • PEXPIREAT <KEY> <timestamp>: 将键的过期时间设为 timestamp 所指定的毫秒数时间戳.

二:保存过期时间

那么redis里面对这些key的过期时间和生存时间的信息是怎么保存的呢??
答:在数据库结构redisDb中的expires字典中保存了数据库中所有键的过期时间,我们称expire这个字典为过期字典。
(1)过期字典是一个指针,指向键空间的某个键对象。
(2)过期字典的值是一个longlong类型的整数,这个整数保存了键所指向的数据库键的过期时间–一个毫秒级的 UNIX 时间戳。

下图是一个带过期字典的数据库例子:

浅谈redis的过期时间设置和过期删除机制

过期字典是存储在redisDb这个结构里的:

?
1
2
3
4
5
6
7
typedef struct redisDb {
    ...
    
    dict *dict;     //数据库键空间,保存着数据库中所有键值对
    dict *expires      // 过期字典,保存着键的过期时间
    ...
} redisDb;

从以上结构中可以看到expire字典(过期字典)和dict字典(数据库键空间,保存着数据库中所有键值对)是并列的,由此可见expire字典的重要性。

三:移除过期时间

PERSIST 命令可以移除一个键的过期时间:

?
1
2
3
4
5
6
7
8
9
10
127.0.0.1:6379> set message "hello"
OK
127.0.0.1:6379> expire message 60
(integer) 1
127.0.0.1:6379> ttl message
(integer) 54
127.0.0.1:6379> persist message
(integer) 1
127.0.0.1:6379> ttl message
(integer) -1

persist命令就是expire命令的反命令,这个函数在过期字典中查找给定的键,并从过期字典中移除。
比如在数据库当前状态(如上图所示),当给book这个key移除过期时间:

?
1
2
redis> persist book
(integer) 1

数据库将更新成如下状态:

浅谈redis的过期时间设置和过期删除机制

可以从图中看到,当PERSIST book命令执行之后,过期字典中的 book 键消失了。

四:计算并返回剩余生存时间

ttl命令以秒为单位返回指定键的剩余生存时间。pttl以毫秒返回。两个命令都是通过计算当前时间和过期时间的差值得到剩余生存期的。

?
1
2
3
4
5
6
7
8
9
10
11
127.0.0.1:6379> set minping shuxin
OK
127.0.0.1:6379> expire minping 60
(integer) 1
127.0.0.1:6379> ttl minping
(integer) 57
127.0.0.1:6379> ttl minping
(integer) 27
127.0.0.1:6379> pttl minping
(integer) 23839
127.0.0.1:6379>

redis源码为:

?
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
void ttlCommand(redisClient *c) {
    ttlGenericCommand(c, 0);
}
void pttlCommand(redisClient *c) {
    ttlGenericCommand(c, 1);
}
void ttlGenericCommand(redisClient *c, int output_ms) {
    long long expire, ttl = -1;
    /* 如果键不存在,返回-2 */
    if (lookupKeyRead(c->db,c->argv[1]) == NULL) {
        addReplyLongLong(c,-2);
        return;
    }
    
    /* 如果键存在*/
    /*如果没有设置生存时间,返回 -1, 否则返回实际剩余时间 */
    expire = getExpire(c->db,c->argv[1]);
    if (expire != -1) {
        /* 过期时间减去当前时间,就是键的剩余时间*/
        ttl = expire-mstime();
        if (ttl < 0) ttl = 0;
    }
    if (ttl == -1) {
        addReplyLongLong(c,-1);
    } else {
         /*将毫秒转化为秒*/
        addReplyLongLong(c,output_ms ? ttl : ((ttl+500)/1000));
    }
}

五:过期键的删除策略

如果一个键是过期的,那它到了过期时间之后是不是马上就从内存中被被删除呢??如果不是,那过期后到底什么时候被删除呢??

其实有三种不同的删除策略:
(1):立即删除。在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理器自动执行键的删除操作。
(2):惰性删除。键过期了就过期了,不管。每次从dict字典中按key取值时,先检查此key是否已经过期,如果过期了就删除它,并返回nil,如果没过期,就返回键值。
(3):定时删除。每隔一段时间,对expires字典进行检查,删除里面的过期键。
可以看到,第二种为被动删除,第一种和第三种为主动删除,且第一种实时性更高。下面对这三种删除策略进行具体分析。

立即删除

立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是立即删除对cpu是最不友好的。因为删除操作会占用cpu的时间,如果刚好碰上了cpu很忙的时候,比如正在做交集或排序等计算的时候,就会给cpu造成额外的压力。

而且目前redis事件处理器对时间事件的处理方式--无序链表,查找一个key的时间复杂度为O(n),所以并不适合用来处理大量的时间事件。

惰性删除

惰性删除是指,某个键值过期后,此键值不会马上被删除,而是等到下次被使用的时候,才会被检查到过期,此时才能得到删除。所以惰性删除的缺点很明显:浪费内存。dict字典和expires字典都要保存这个键值的信息。

举个例子,对于一些按时间点来更新的数据,比如log日志,过期后在很长的一段时间内可能都得不到访问,这样在这段时间内就要拜拜浪费这么多内存来存log。这对于性能非常依赖于内存大小的redis来说,是比较致命的

定时删除

从上面分析来看,立即删除会短时间内占用大量cpu,惰性删除会在一段时间内浪费内存,所以定时删除是一个折中的办法。
定时删除是:每隔一段时间执行一次删除操作,并通过限制删除操作执行的时长和频率,来减少删除操作对cpu的影响。另一方面定时删除也有效的减少了因惰性删除带来的内存浪费。

六:redis使用的策略

redis使用的过期键值删除策略是:惰性删除加上定期删除,两者配合使用。

到此这篇关于浅谈redis的过期时间设置和过期删除机制的文章就介绍到这了,更多相关redis的过期时间设置和过期删除内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/jiangchunhui2009/article/details/81504073

延伸 · 阅读

精彩推荐
  • RedisRedis List列表的详细介绍

    Redis List列表的详细介绍

    这篇文章主要介绍了Redis List列表的详细介绍的相关资料,Redis列表是简单的字符串列表,按照插入顺序排序,需要的朋友可以参考下 ...

    大白能2902019-11-07
  • Redis使用redis实现附近的人功能

    使用redis实现附近的人功能

    这篇文章主要介绍了使用redis实现附近的人,实现诸如附近的人这类依赖于地理位置信息的功能,本文通过实例代码给大家介绍的非常详细,需要的朋友可以...

    Java是最好的语言√9502021-11-17
  • RedisRedis三种集群模式详解

    Redis三种集群模式详解

    redis有三种集群模式,其中主从是最常见的模式,今天通过本文给大家分享Redis三种集群模式介绍,感兴趣的朋友一起看看吧...

    coffeebabe3842021-11-19
  • RedisRedis Cluster 字段模糊匹配及删除

    Redis Cluster 字段模糊匹配及删除

    在数据库内我们可以通过like关键字、%、*或者REGEX关键字进行模糊匹配。而在Redis内我们如何进行模糊匹配呢?本文就来介绍一下...

    在风中的意志10162021-08-06
  • RedisRedis高级数据类型Hyperloglog、Bitmap的使用

    Redis高级数据类型Hyperloglog、Bitmap的使用

    很多小伙伴在面试中都会被问道 Redis的常用数据结构有哪些?可能很大一部分回答都是 string、hash、list、set、zset,但其实还有Hyperloglog和Bitmap,本文就来介...

    Code皮皮虾7732021-08-05
  • RedisRedis实现分布式队列浅析

    Redis实现分布式队列浅析

    Redis将数据存储在内存中,使得读写速度非常快,经常被用来做缓存系统,这里我们将redis用来做一个分布式的消息队列。这篇文章主要介绍了使用redis来作...

    ioiogoo5412019-10-31
  • Redis详解Redis集群搭建的三种方式

    详解Redis集群搭建的三种方式

    Redis是一个开源的key-value存储系统,大部分互联网企业都用来做服务器端缓存。Redis在3.0版本前只支持单实例模式,虽然支持主从模式、哨兵模式部署来解决...

    八重樱8732021-08-08
  • Redisredis protocol通信协议及使用详解

    redis protocol通信协议及使用详解

    这篇文章主要为大家介绍了redis protocol通信协议及使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪...

    程序那些事10162022-07-16