《Redis设计与实现》第九章总结二:过期键相关操作

继《Redis设计与实现》第九章总结一:数据库相关操作实现

1.6 服务器保存键的生存时间和过期时间的实现方法

1.6.1 概述

客户端使用EXPIRE或PEXPIRE命令可以以秒或毫秒精度为数据库的某个键设置生存时间(TTL);
经过指定时间后,服务器会自动删除生存时间为0的键

EXPIREAT或PEXPIREAT命令则以秒或毫秒精度为数据库的某个键设置过期时间(expire time),SETEX命令则只针对字符串键;
当键的过期时间来临时,服务器会自动从数据库中删除这个键

TTL和PTTL命令接受一个带有生存时间或者过期时间的键,返回这个键的剩余生存时间,即返回距离这个键被服务器删除还有多长时间

1.6.2 设置生存/过期时间

有四个不同命令可以设置键的生存时间(键可以存在多久,如5秒之后)或过期时间(键什么时候会被删除,如1377257300这个时间点被删除):
《Redis设计与实现》第九章总结二:过期键相关操作_第1张图片
EXPIRE/PEXPIRE/EXPIREAT这三个命令都是由第四个命令PEXPIREAT命令实现的,最终转化之后的执行效果都和执行PEXPIREAT命令一样

EXPIRE:先转化为PEXPIRE,再由PEXPIRE转化为PEXPIREAT:
EXPIRE转化为PEXPIRE:
《Redis设计与实现》第九章总结二:过期键相关操作_第2张图片
PEXPIRE转化为PEXPIREAT:生存时间转化为过期时间,获取当前时间,加上生存时间即可
《Redis设计与实现》第九章总结二:过期键相关操作_第3张图片
EXPIREAT转化为PEXPIREAT:
《Redis设计与实现》第九章总结二:过期键相关操作_第4张图片
总结:
《Redis设计与实现》第九章总结二:过期键相关操作_第5张图片

1.6.3 保存过期时间

redisDb结构的expired字典保存了所有键的过期时间,此字典被称为过期字典
过期字典键值对含义:键是一个指针,指向键空间中的某个键对象,值是一个long long类型的整数,保存了键所指向的数据库键的过期时间——一个毫秒精度的UNIX时间戳
《Redis设计与实现》第九章总结二:过期键相关操作_第6张图片
例子:
《Redis设计与实现》第九章总结二:过期键相关操作_第7张图片
注意:上图为了展示方便,出现了两次book键和alphabet键,实际上键空间的键和过期字典的键都会指向同一个键对象,不会出现重复,浪费空间

保存:客户端使用PEXPIREAT命令(或其他三个会转换成PEXPIREAT命令的命令)

伪代码实现PEXPIREAT:
《Redis设计与实现》第九章总结二:过期键相关操作_第8张图片

1.6.4 移除过期时间

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

伪代码实现PERSIST:
《Redis设计与实现》第九章总结二:过期键相关操作_第9张图片

1.6.5 计算并返回剩余生存时间

TTL以秒为单位返回键的剩余生存时间,PTTL则以毫秒返回

伪代码实现PTTL、TTL:核心是过期时间减去当前时间
《Redis设计与实现》第九章总结二:过期键相关操作_第10张图片

1.6.6 过期键的判定

  • 方法

1.检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间

2.检查当前UNIX时间戳是否大于键的过期时间:如果是的话,那么键已经过期,否则的话,键未过期

也可以直接通过TTL判定,实际中用的是上面的方法,因为直接访问字典比执行一个命令稍微快一些

伪代码is_expired:
《Redis设计与实现》第九章总结二:过期键相关操作_第11张图片

1.7 过期键的删除/处理策略

删除策略分三种:定时删除、惰性删除、定期删除

1.7.1 定时删除

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

优点:对内存友好

缺点:对CPU不友好。删除键比较耗时,且创建一个定时器需要触发时间事件,而时间事件的实现方式为无序链表,查找一个事件的事件复杂度为O(N),每次创建都要执行一次O(N),较慢

1.7.2 惰性删除

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

优点:CPU友好,保证了删除只会在非做不可的情况下进行,且仅限于当前键

缺点:内存不友好,可能会造成一种内存泄露:可能有大量的过期键不被访问,则一直不会被清除,如日志键

1.7.3 定期删除

含义:每隔一段时间,程序就对数据库进行一次检查,删除过期键;由算法来决定要删除多少过期键,检查多少个数据库

注意:是定时删除和惰性删除的一种折中

难点:如何确定删除操作执行的时长和频率。太频繁或太长,则退化成定时删除策略;太少或太短,则退化成惰性删除策略

1.7.4 Redis过期键删除策略

Redis使用惰性删除和定期删除的配合,在CPU和内存之间取得平衡

1.7.4.1 惰性删除策略的实现

db.c/expireIfNeeded函数实现,进行读写操作时,都会先调用此函数对输入键进行检查:
在这里插入图片描述
思想:过滤器

注:因为每个键都可能被访问且因为键过期被删除,每个被访问的键都必须能够同时处理键存在以及键不存在两种情况,键存在时,则按存在的情况执行;不存在时,则按不存在的情况执行,如返回空回复

1.7.4.2 定期删除策略的实现

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

1.7.5 AOF、RDB和复制功能对过期键的处理

1.7.5.1 RDB处理
  • 生成RDB文件时

执行SAVE/BGSAVE命令创建一个新的RDB文件时,程序会检查键,已过期的键不会被保存到新创建的RDB文件中

  • 载入RDB文件时

启动Redis服务器时,如果开启了RDB功能,那么服务器将对RDB文件进行载入,分为主服务器和从服务器模式:
《Redis设计与实现》第九章总结二:过期键相关操作_第12张图片
注意:如上图所说,主从服务器在进行数据同步时,从服务器数据库会被清空

1.7.5.2 AOF处理
  • AOF文件写入时

当服务器以AOF持久化模式运行时,如果数据库中的某个键已经过期,但它还没有被惰性删除或定期删除,那么AOF文件不会因为这个过期键而产生任何影响;若被惰性删除或定期删除,程序会向AOF文件追加(append)一条DEL命令,来显示地记录该键已被删除

例子:GET message,该message已过期
在这里插入图片描述

  • AOF重写时

类似生成RDB文件:执行AOF重写的过程中,程序会检查键,已过期的键不会被保存到重写后的AOF文件中

1.7.5.3 复制处理

服务器运行在此模式下时,从服务器的过期键删除策略由主服务器控制,保证主从服务器的数据一致性:
《Redis设计与实现》第九章总结二:过期键相关操作_第13张图片

你可能感兴趣的:(Redis,Redis设计与实现)