继《Redis设计与实现》第九章总结一:数据库相关操作实现
客户端使用EXPIRE或PEXPIRE命令可以以秒或毫秒精度为数据库的某个键设置生存时间(TTL);
经过指定时间后,服务器会自动删除生存时间为0的键
EXPIREAT或PEXPIREAT命令则以秒或毫秒精度为数据库的某个键设置过期时间(expire time),SETEX命令则只针对字符串键;
当键的过期时间来临时,服务器会自动从数据库中删除这个键
TTL和PTTL命令接受一个带有生存时间或者过期时间的键,返回这个键的剩余生存时间,即返回距离这个键被服务器删除还有多长时间
有四个不同命令可以设置键的生存时间(键可以存在多久,如5秒之后)或过期时间(键什么时候会被删除,如1377257300这个时间点被删除):
EXPIRE/PEXPIRE/EXPIREAT这三个命令都是由第四个命令PEXPIREAT命令实现的,最终转化之后的执行效果都和执行PEXPIREAT命令一样
EXPIRE:先转化为PEXPIRE,再由PEXPIRE转化为PEXPIREAT:
EXPIRE转化为PEXPIRE:
PEXPIRE转化为PEXPIREAT:生存时间转化为过期时间,获取当前时间,加上生存时间即可
EXPIREAT转化为PEXPIREAT:
总结:
redisDb结构的expired字典保存了所有键的过期时间,此字典被称为过期字典
过期字典键值对含义:键是一个指针,指向键空间中的某个键对象,值是一个long long类型的整数,保存了键所指向的数据库键的过期时间——一个毫秒精度的UNIX时间戳
例子:
注意:上图为了展示方便,出现了两次book键和alphabet键,实际上键空间的键和过期字典的键都会指向同一个键对象,不会出现重复,浪费空间
保存:客户端使用PEXPIREAT命令(或其他三个会转换成PEXPIREAT命令的命令)
PERSIST命令可以移除一个键的过期时间
TTL以秒为单位返回键的剩余生存时间,PTTL则以毫秒返回
1.检查给定键是否存在于过期字典:如果存在,那么取得键的过期时间
2.检查当前UNIX时间戳是否大于键的过期时间:如果是的话,那么键已经过期,否则的话,键未过期
也可以直接通过TTL判定,实际中用的是上面的方法,因为直接访问字典比执行一个命令稍微快一些
删除策略分三种:定时删除、惰性删除、定期删除
含义:设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作
优点:对内存友好
缺点:对CPU不友好。删除键比较耗时,且创建一个定时器需要触发时间事件,而时间事件的实现方式为无序链表,查找一个事件的事件复杂度为O(N),每次创建都要执行一次O(N),较慢
含义:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键
优点:CPU友好,保证了删除只会在非做不可的情况下进行,且仅限于当前键
缺点:内存不友好,可能会造成一种内存泄露:可能有大量的过期键不被访问,则一直不会被清除,如日志键
含义:每隔一段时间,程序就对数据库进行一次检查,删除过期键;由算法来决定要删除多少过期键,检查多少个数据库
注意:是定时删除和惰性删除的一种折中
难点:如何确定删除操作执行的时长和频率。太频繁或太长,则退化成定时删除策略;太少或太短,则退化成惰性删除策略
Redis使用惰性删除和定期删除的配合,在CPU和内存之间取得平衡
db.c/expireIfNeeded函数实现,进行读写操作时,都会先调用此函数对输入键进行检查:
思想:过滤器
注:因为每个键都可能被访问且因为键过期被删除,每个被访问的键都必须能够同时处理键存在以及键不存在两种情况,键存在时,则按存在的情况执行;不存在时,则按不存在的情况执行,如返回空回复
redis.c/activeExpireCycle函数实现,当周期性操作redis.c/serverCron函数执行时,activeExpireCycle就会被调用,此函数在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键
执行SAVE/BGSAVE命令创建一个新的RDB文件时,程序会检查键,已过期的键不会被保存到新创建的RDB文件中
启动Redis服务器时,如果开启了RDB功能,那么服务器将对RDB文件进行载入,分为主服务器和从服务器模式:
注意:如上图所说,主从服务器在进行数据同步时,从服务器数据库会被清空
当服务器以AOF持久化模式运行时,如果数据库中的某个键已经过期,但它还没有被惰性删除或定期删除,那么AOF文件不会因为这个过期键而产生任何影响;若被惰性删除或定期删除,程序会向AOF文件追加(append)一条DEL命令,来显示地记录该键已被删除
类似生成RDB文件:执行AOF重写的过程中,程序会检查键,已过期的键不会被保存到重写后的AOF文件中