Redis的数据库
服务器
struct redisServer{
//...
//一个数组,保存着服务器中的所有数据库
redisDb *db;
//...
};
![](https://img.haomeiwen.com/i11774306/92013d0d27aa6665.png)
客户端
typedef struct redisClient{
//...
//记录客户端当前正在使用的数据库
redisDb *db;
//...
}redisClient;
- 初始化服务器的时候程序会根据dbnum的属性来创建多少个数据库。默认值为16。
- 在切换数据库的时候(使用SELECT指令)客户端会更改redisDb指针的指向。
键空间
typedef struct redisDb{
//...
//数据库键空间,保存了数据库中所有的键值对
dict *dict;
//...
}redisDb;
Redis是一个键值对数据库服务器,服务器中的每个数据库都有一个dict字典保存数据库中所有的键值对。
每个键都是字符串对象,值可以是字符串对象、列表对象、哈希对象、集合对象和有序集合对象。
时间操作
通过EXPIRE命令或者PEXPTRE命令,客户端可以以秒或者毫秒为精度为数据库的键空间中的某个键设置生存时间,在经过指定时间之后,服务器就会自动删除过期时间为0的键。
过期时间是一个时间戳,当键的过期时间来临时,服务器会自动从数据库中删除这个键。
设置过期时间
- EXPIRE <key> <ttl> 将键的生存时间设置为ttl秒
- PEXPIRE <key> <ttl> 命令将键的生存时间设置为ttl毫秒
- PEXPIREAT <key> <timestamp> 命令将键key的过期时间设置为timestamp所指定的毫秒数时间戳。
【注意】虽然有不同的设置生存时间的方式,但是最终都会转换为时间戳的形式保存在过期字典中。
保存过期时间
Redis数据库中有一个expire字典中保存了数据库中所有键的过期时间,称这个字典为过期字典。
过期字典的键是一个指针,这个指针指向键空间中的某个键对象。
过期字典的值是一个long long类型的整数,这个整数保存了指键指向数据库键的过期时间。
移除过期时间
PERPIST <key>
移除过期字典中指定的键。
计算剩余时间
TTL <key>:计算指定键的剩余秒数
PTTL <key>:计算指定键的剩余毫秒数
剩余时间 = 过期时间戳 - 当前时间戳
过期键的判定
- 检查给定键是否存在于过期字典,存在取得键的过期时间。
- 检查当前时间戳是否大于过期时间戳,是的话,那么键已经过期。
过期键的删除
-
定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键过期时间来临时,立即执行对键的删除操作。
a) 优点:保证键尽可能块的被删除,并释放所占内存。
b) 缺点:对CPU不友好,如果CPU资源紧张,会对服务器的响应时间和吞吐量造成影响。
创建定时器需要用到Redis的时间事件,而当前时间的实现方式为无序链表,所以查找一个事件的时间复杂度为O(N),所以并不能高效的处理大量时间事件。 -
惰性删除:放任过期键不管,每次从键空间获取键的时候,会检查取得的键是否过期,如果过期的话,删除该键。
a) 对CPU友好,但是如果过期键很多的话会占用大量的内存。而且去过一个键永远不去访问,会造成无法释放,造成内存泄漏。 -
定期删除:每个一段时间,检查一次数据库中的键。
定期删除是前两种策略的折中,可以减少上面出现的问题,但是对于删除执行的时长和频率很难确定。
Redis的过期删除策略:
Redis使用惰性删除和定期删除两种策略。
Redis惰性删除实现
所有读写数据库的Redis命令在执行之前都会调用特定的函数对输入键进行检查,过期的键就会被删除。
Redis定期删除实现
- redis服务器会定期执行一个删除过期键的函数,函数每次运行都会从数据库中取出一定数量的随机键进行检查,并删除其中的过期键。
- 有一个全局变量会记录已经删除完过期键的数据库,当函数再次调用的时候,会继续从原来的进度进行工作,检查完一个数据库,全局变量+1,加到15后,全局变量变为0,重新检查。
RDB对过期键
生成RDB文件时,会对过期键进行忽略,数据库中包含过期键不会生成新的RDB文件造成影响。
载入RDB文件时,如果服务器开启了RDB功能,服务器会对文件进行自动载入,
如果服务器以主服务器模式运行,在载入RDB文件时,会对文件中保存的所有的键进行检查,未过期的键会被载入到数据库中,过期的键会被忽略。
如果服务器以从服务器模式运行,那么在载入RDB文件时,文件中保存的所有的键,无论是否过期都会被载入到数据库中,(主服务器在进行数据同步的时,从服务器的数据库就会被清空)
AOF对过期键
AOF文件写入
如果数据库中的某个键已经过期,但他还没有被惰性删除或者定期删除,那么AOF文件不会因为这个过期键产生任何影响。
如果过期键被定期删除或者惰性删除之后,程序会向AOF文件追加一条del命令标志该键已被删除。
AOF文件重写
程序会对数据库中的键进行检查,已过期的键不会被载入到数据库中。
复制对过期键
- 主服务器删除一个过期键之后,会显示的向所有服务器发送一个DEL命令,告诉从服务器删除这个键。
- 从服务器在执行客户端发送读命令时,即使碰到过期键也不会将过期键删除,而是向处理未过期键一样来处理过期键。
- 从服务器之后收到主服务器的DEL命令之后,才会删除过期键。
这样做的目的可以保证主从一致。