redis数据库

Redis服务器将所有数据库都保存在redis.h/redisServer的结构中
struct redisServer {
//一个数组保存着服务器中所有数据库
redisDb *db;
//服务器中的数据库数量
int dbnum;
//..............
};

数据库键空间

Redis是一个键值对数据库服务器,redisDb结构的dict字典保存了数据库中的所有键值对,我们称这个字典为键空间。
typedef struct redisDb {
//数据库键空间,保存着数据库中的所有键值对
dict *dict;
//保存所有设置过期时间的键和过期时间
dict *expires;
} redisDb;
键空间的每个键都是一个字符串对象,每个值可以是字符串对象,列表对象,哈希表对象,集合对象和有序集合对象的一种。

读写键空间的维护操作

  • 读取一个键后(读操作和写操作都要对键进行读取),服务器会根据键是否存在来更新服务器的键空间命中(hit)次数或键空间不命中(miss)次数,这两个值可以在INFO stats命令的keyspace_hits属性和keyspace_misses属性中查看。
    *在读取一个键后,服务器会更新键的LRU(最后一次使用)时间,这个值可以用于计算键的闲置时间,使用OBJECT idletime命令可以查看键key的闲置时间。
    *如果服务器在读取一个键时发现该键已经过期,那么服务器会先删除这个过期键,然后才执行余下的其他操作。
    *如果有客户端使用WATCH命令监视了某个键,那么服务器在对被监视的键及进行修改之后,会将这个键标记为脏(dirty),从而让事务程序注意到这个键已经被修改过。
    *服务器每次修改一个键之后,都会对脏(dirty)键计数器的值增1,这个计数器会触发服务器的持久化以及复制操作。
    *如果服务器开启了数据库通知功能,那么在对键进行修改之后,服务器将按配置发送相应的数据库通知。

设置键的生存时间或过期时间

Redis 有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除) :
EXPlRE 命令用于将键key 的生存时间设置为ttl 秒。
PEXPIRE 命令用于将键key 的生存时间设置为ttl 毫秒。
EXPIREAT < timestamp> 命令用于将键key 的过期时间设置为timestamp所指定的秒数时间戳。
PEXPIREAT < timestamp > 命令用于将键key 的过期时间设置为timestamp所指定的毫秒数时间戳。
但实际上EXPlRE、PEXPlRE 、EXPIREAT三个命令都是使用PEXPlREAT 命令来实现的:无论客户端执行的是以上四个命令中的哪一个, 经过转换之后,最终的执行效果都和执行PEXPlREAT 命令一样

保存过期时间
redisDB结构的expires字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典

  • 过期字典的键是一个指针,这个指针指向键空间中的某个键对象( 也即是某个数据库键)。
  • 过期字典的值是一个long类型的整数,这个整数保存了键所指向的数据库键的过期时间:一个毫秒精度的UNIX 时间戳。

过期键的删除策略,reids使用的是惰性删除和定期删除两种策略

1、定时删除:设置键的过期时间的同时,创建一个定时器,然后在键过期的时候自动触发删除操作。缺点是他对CPU时间不友好,另外创建一个定时器需要用到Redis服务器中的时间事件,因为时间事件底层是通过无序链表实现的,查找一个事件时间复杂度为O(N).
2、惰性删除:就是在获取键的时候,检查键是否过期,如果过期的话,执行删除操作。优点对CPU最友好,缺点是对内存最不友好。如果一个键已过期而这个键又不再被访问的话就永久不会被删除。所有读写数据库的redis命令在执行前都会调用expireIfNeeded函数对键进行检查,如果已过期expireIfNeeded函数删除键。
3、定期删除:每隔一段时间,检查数据库中的键是否过期,如果过期的话,执行删除操作。难点是确定删除操作的时长和频率。每当Redis服务器周期性执行serverCron函数时,activeExpireCycle函数就会调用。activeExpireCycle工作模式总结:

  • 函数每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键。
  • 全局变量current_db会记录当前activeExpireCycle函数检查的进度,并在下一次 activeExpireCycle函数调用时,接着上一次的进度进行处理。比如说,如果当前 *
    activeExpireCycle函数在遍历10号数据库时返回了,那么下次activeExpireCycle函数执行时,将从11号数据库开始查找并删除过期键
  • 随着activeExpireCycle函数的不断执行,服务器中的所有数据库都会被检查一遍,这时函数将current_db变量重置为0,然后再次开始新一轮的检查工作

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

  • 在执行SAVE命令或者BGSAVE命令创建一个新RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到RDB文件中。
  • 如果服务器以主服务器模式运行,那么载入RDB文件时,程序会文件中的键进行检查,过期的键则被忽略。如果已从服务器模式运行,那么载入RDB文件时,文件中的键是否过期都会被载入。
  • 当服务器执行AOF重写的过程中,程序会对数据库中的键进行检查,过期后的键不会被保存到重写后的AOF文件。
  • 当服务器运行在复制模式时,从服务器的过期键删除动作由主服务器控制。
posted @ 2021-02-28 21:51  wenlongliu  阅读(31)  评论(0编辑  收藏  举报