Redis设计与实现——第二部分 单机数据库的实现 第10章 rdb持久化

Redis数据库状态:服务器中的非空数据库以及它们的键值对统称为数据库状态。
因为Redis是内存数据库,它将自己的数据库状态存储在内存里面,所以如果不想办法将存储在内存总的数据库状态保存到磁盘里面,那么一旦服务器进程退出,服务器中的数据库状态也会消失不见。
Redis rdb持久化功能,可以把某个时间点上redis在内存中的数据库状态保存到磁盘里面一个RDB二进制文件中,避免数据意外丢失,redis服务器可以用它来还原数据库状态。

RDB文件的创建与载入
有两个命令可以用于生成RDB文件,一个是save(阻塞Redis服务器进程),另一个是bgsave(派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程继续处理命令请求)。

def SAVE() :

创建RDB文件

rdbSave()
def BGSAVE() :

创建子进程

pid = fork()
if pid ==0 :

子进程负责创建RDB文件

rdbSave()

#完成之后向父进程发送信号
signal_parent()

elif pid > 0 :

父进程继续处理命令请求,并通过轮训等待子进程的信号

handle_request_and_wait_signal()
else :

处理出错情况

handle_fork_error()

利用save命令或者bgsave命令创建rdb文件不同,rdb文件的载入工作是在服务器启动时自动执行的,所以Redis并没有专门用于载入rdb文件的命令,只要redis服务器在启动的时候检测到rdb文件存在,它就会自动载入rdb文件。另外,因为aof文件的更新频率通常比rdb文件的更新频率高,所以1.如果服务器开启了aof持久化功能,那么服务器会优先使用aof文件来还原数据库状态 2.只有aof处于关闭状态时,服务器才会使用rdb文件来还原数据库状态。

在这里插入图片描述

save命令执行时的服务器状态
当save命令执行时,redis服务器会被阻塞,所以当save命令正在执行时,客户端发送的所有命令请求都会被拒绝。
bgsave命令执行时服务器的状态
客户端命令可以继续处理。
save命令禁止执行,两个命令同时调用rdbSave,防止产生竞争条件。
其次,在bgsave命令执行期间,客户端发送的bgsave命令会被服务器拒绝,防止产生竞争条件。
再其次,如果客户端发送bgrewriteaof命令会被延迟到bgsave命令执行完成

如果bgrewriteaof在执行,bgsave命令会被拒绝。
bgrewriteaof和bgsave这两个命令的实际工作都由子进程执行,所以这个两个命令在操作方面并没有什么冲突的地方,不能同时执行它们只是性能考虑,并发出两个子进程,并且这两个子进程都同时执行大量的磁盘写入操作,这怎么想都不是一个好主意。

RDB文件载入时服务器一直处于阻塞状态,知道载入工作完成。

自动间隔性保存
bgsave可以在不阻塞服务器进程的情况下执行,所以redis允许用户通过设置服务器配置的save选项,让服务器每隔一段时间执行一次bgsave命令。
用户可以通过设置save选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行bgsave命令。

设置保存条件
如果没有设置save选项,那么服务器会为save选项设置默认条件。
save 900 1
save 300 10
save 60 10000
接着服务器程序会根据save选项所设置的保存条件,设置服务器状态redisServer结构的saveparams属性:
struct redisServer {
// 记录了保存条件的数组
struct saveparam *saveparams;
}

struct saveparam {
//秒数
time_t seconds;
//修改数
int changes;
};

在这里插入图片描述

dirty计数器和lastsave属性
除了saveparams数组之外,服务器状态还维持着一个dirty计数器,以及一个lastsave属性:
1.dirty计数器记录距离上一次成功执行save命令或者bgsave命令之后,服务器对数据库状态进行了多少次修改
2.lastsave属性是一个unix时间戳,记录了服务器上一次执行save命令或bgsave命令的时间。

struct redisServer {
//修改计数器
long long dirty ;
//上一次执行保存的时间 save|bgsave
time_t lastsave;
}

检查保存条件是否满足
redis的服务器周期性操作函数serverCron默认每隔100毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是检查save选项所设置的保存条件是否满足,如果满足就执行bgsave命令。
在这里插入图片描述
bgsave执行完后,更新lastsave和dirty计数器。

rdb文件结构
在这里插入图片描述
redis,redis字符串
db_version rdb版本 ‘0006’第6版
databases部分包含0个或任意多个数据库,以及各个数据库中的键值对数据
EOF常量长度为1字节,这个常量标志着RDB文件正文内容的结束。
check_sum是一个8字节长的无符号整数,保存着一个校验和。这个校验和是程序通过REDIS、db_version、databases、EOF四个部分的内容计算得出的。服务器在载入RDB文件时,会将载入数据所计算出的校验与check_sum所记录的校验和进行对比,以此来检查rdb文件是否有出错后者损坏的情况出现。
在这里插入图片描述

当程序读入db_number部分之后,服务器会调用select命令,根据读入的数据库号码进行数据库切换,使得之后读入的键值对可以载入到正确的数据库中。

key_value_pairs部分
保存了一个或以上数量的键值对
不带过期时间的键值对:
在这里插入图片描述

带过期时间的键值对
在这里插入图片描述

value编码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章