redis之RDB持久化底层实现
推荐书籍:《Redis设计与实现》
一,RDB的持久化
1,数据库状态:服务器中非空数据库和他们的含有的键值对称为数据库状态;
2,RDB文件:可以手动执行持久化命令生成RDB文件,也可以配置对应的选项自动化执行持久化命令
3,RDB文件:是一个经过压缩的二进制文件;
二,RDB文件的创建和载入
1,生成RDB文件的命令
a,SAVE命令:执行SAVE命令之后,会阻塞服务器进程,直至RDB文件创建完成为止;在服务器阻塞期间,服务器不能处理来自客户端的命令;
b,BGSAVE命令:执行SAVE命令之后,会创建一个子进程来完成RDB文件的创建,在此期间,服务器可以处理来自客户端的命令;
2,载入RDB文件
redis没有提供RDB文件载入的命令,在服务器启动的时候,会自动检测是否存在RDB文件,如果存在,那么自动进行载入;
3,注意
持久化的方式有两种,一种AOF,一种是RDB,由于AOF更新频率更高,因此:
如果服务器开启了AOF持久化功能,那么优先使用AOF文件进行载入; 如果没有开启AOF持久化功能,那么就会使用RDB文件还原数据库状态;
4,在执行BGSAVE命令的时候,服务器的状态
在执行BGSAVE命令的时候,服务器可以接受来自客户端的命令,并进行处理;但是有些命令在此时不能被执行,如SAVE,BGSAVE,BGREWRITEAOF;
5,RDB文件载入时服务器的状态
会一直处于阻塞状态,直至文件载入完毕;
三,自动间隔性保存
1,自动间隔性保存的实现
通过配置save选项,让服务器每隔一段时间自动执行一次BGSAVE命令;并且用户可以同时配置多个save条件,只要满足其中一个就会执行BGSAVE;
2,举例
3,自动间隔性保存的实现原理
a,使用一个saveParam数组来保存所有的save选项,saveParam有两个属性,一个是seconds,changes;
b,服务器还会维持两个属性dirty和lastSave;
dirty记录在上一次执行了SAVE和BGSAVE之后,服务器对数据库的状态改变了多少次;
lastSave记录了上一次执行SAVE或者BGSAVE的时间;
c,服务器每隔100毫秒就会执行一次serverCron函数,来判断当前是否要执行BGSAVE命令;serverCron函数的实现原理就是遍历saveParam数组中的每一个saveParam和dirty,lastSave进行对比,看是否需要执行BGSAVE;
四,RDB文件结构
1,RDB文件所包含的部分
a,REDIS:占5个字节空间,存储着"REDIS"五个字符;作用就是在服务器加载该文件的时候,可以快速判断出该文件是否是一个RDB文件;
b,db_version:占4个字节空间,记录了rdb文件的版本号;如:0006就表示所使用的的rdb文件版本为第6版;
c,database:包含着0个或多个数据库,以及各个数据库中键值对数据;下面会进行详细介绍;
d,EOF:占1个字节空间,作用就是标志着RDB文件正文内容结束,当读入程序遇到这个值的时候,表示所有数据库中所有键值对已经被载入完毕了;
e,check_sum:占8个字节空间,是一个检验和,通过前4个部分计算出的,主要用来检验rdb文件是否出错或者有损坏;服务器载入REDIS,db_version,database,EOF四部分那内容,计算出来的值和check_sum进行比较,来判断rdb文件是否有问题;
2,database部分详细介绍
a,一个RDB文件的database部分保存任意多个非空数据库,如下所示
b,每个database的结构,如下所示
SELECTED:占1个字节的空间,当程序遇到这个值得时候,表示接下来将会遇到的值将会是一个数据库号码;
db_number:占据空间大小,由号码大小决定;db_number表示一个数据库号码;当程序读到这个号码之后,会调用select命令,根据读入的数据库号码进行数据库切换;
key_value_pairs:保存了数据库中所有的键值对;
c,key_value_pairs的具体结构(不带过期时间),如下所示
TYPE:占1个字节,记录了value的类型;如String,list,set,hash等;
key:记录键值对的键
value:记录键值对的值;
d,key_value_pairs的具体结构(带过期时间),如下所示
EXPIRETIME_MS:用来告诉程序接下来读入是一个过期时间;
ms:是一个unix时间戳,表示key的过期时间;