Redis服务器的所有数据库都保存在redisServer结构的db数组中,根据dbnum属性初始化数据库的数量;
struct redisServer{ //..... //一个数组,保存服务器中的所有数据库 redisDb *db; //服务器的数据库数量,默认16个 int dbnum; }
切换数据库:select 1;
服务器的内部,客户端状态redisClient结构记录客户端的状态
typedef struct redisclient{ //记录客户端当前使用的数据库 redisDb *db; }redisClient
Redis是一个键值对(key-value pair)数据库服务器,服务器中的每个数据库信息由redisDb保存,其中有个属性dict字典保存所有的键值对,这个字典就是键空间。
typedef struct redisDb{ //数据库键空间,保存着数据库中所有键值对 dict *dict; }
EXPIRE KEY TTL:将键key的生存时间设置为ttl秒
PEXPIRE KEY TTL:将键key的生存时间设置为ttl毫秒
EXPIRE KEY TIMESTAMP:将键key的过期时间设置为timestamp所指定的秒数时间戳
PEXPIRE KEY TIMESTAMP:将键key的过期时间设置为timestamp所指定的毫秒数时间戳
PERSIST key:移除过期时间。
TTL:计算键的过期时间与当前时间之差,以秒为单位返回。
PTTL:计算键的过期时间与当前时间之差,以豪秒为单位返回。
redisDb结构的属性expires字典保存数据库中所有键的过期时间,这个字典称为过期字典。
typedef struct redisDb{ //过期字典,保存着键的过期时间 dict *expires; }
键的过期删除策略有三种:
在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会保存到新创建的RDB文件中;
主服务器在载入RDB文件的时候,会对过期键进行筛选,不将过期的键录入,而从服务器在载入RDB文件的时候,会将过期的键也录入;
当服务器以AOF模式运行时,不会收到过期键的影响,当过期键被惰性删除或定期删除后,AOF文件会追加一条DEL命令来显式地删除该键。
AOF重写的时候,不会将过期的键写入文件。
复制模式下,从服务器不会主动去删除过期的键,都是由主服务器去控制,当主服务器向从服务器发送删除命令的时候,从服务器才回去删除过期的键。
数据库状态:服务器中的非空数据库及其键值对
RDB文件:一个压缩的二进制文件,用来记录数据库状态
SAVE:阻塞Redis服务器进程,直到RDB文件创建完毕为止。
BGSAVE:命令会派生出子进程,由子进程去完成RDB文件创建,父进程继续响应命令处理。
AOF文件的更新频率会比RDB文件的更新频率高,所以如果服务器启动了AOF持久化功能,服务器会优先使用AOF文件还原数据库状态
服务器默认的保存策略
SAVE 900 1:服务器在900秒内,对数据库进行了至少一次修改;
SAVE 300 10:服务器在300秒内,对数据库进行了至少10次修改;
SAVE 60 10000:服务器在60秒内,对数据库进行了至少10000次修改;
保存条件的数据结构
struct redisServer{ //记录保存条件的数组 struct saveparam *saveparams; } struct saveparam{ //秒数 time_t seconds; //修改数 int changes; }
redis | db_version | databases | eof | check_sum
redis:文件头,保存REDIS字符用于标识文件;
db_version:长度4字节 ,记录RDB文件版本号;
databases:包含零个或任意多个数据库,以及各数据库中的键值对数据;
保存的数据结构为:SELECTDB | db_number | key_value_pairs
eof:常量的长度为1字节,标识RDB文件正文结束;
check_sum:8字节长的无符号整数,保存校验和。
打印RDB文件:od -c dump.rdb
AOF持久化时通过保存Redis服务器执行的写命令来记录数据状态,被写入AOF文件的所有命令都是以Redis命令请求协议。AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步。
当AOF持久化功能开启,服务器在执行一个命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。
struct redisServer{ //AOF缓冲区 sds aof_buf; }
Redis服务器进程实质上是一个事件循环,循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,时间事件则负责定时运行函数。
服务器在处理文件事件时都可能会执行写命令,使得一些内容被追加到aof_buf缓冲区,每次服务器结束一个事件循环前,都会调用flushAppendOnlyFile函数,决定是否将缓冲区中的内容写入到文件。
appendfsync选项的值 | flushAppendOnlyFile函数 |
---|---|
always | 将aof_buf缓冲区中的所有内容写入并同步到AOF文件 |
everysec | 每隔一秒将缓冲区的内容写入AOF文件 |
no | 不将将aof_buf缓冲区的内容写入AOF文件 |
AOF文件载入和数据还原的时候,现在本地创建一个伪客户端,读取AOF文件中的命令,将命令用伪客户端执行,还原数据库状态。
AOF文件重写并不需要对已有的AOF进行读取,而是通过读取服务器当前的数据状态来实现。
AOF文件重写的时候,服务器会开辟一个新的重写缓冲区空间,当命令进入时,会将命令记录在AOF缓冲区和AOF重写缓冲区,当且仅当AOF的新文件生成后,向父进程发送信号,然后再将AOF重写缓冲区的内容录入AOF文件,原子性地将新的AOF文件替换旧的AOF文件。