一、RDB文件的创建和载入
1、save和bgsave
save命令会阻塞redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。
bgsave命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。
RDB文件的载入工作是在服务器启动时自动执行的,redis并没有专门用于在载入RDB文件的命令,只要redis服务器在启动时检测到RDB 文件存在,它就会自动载入RDB文件。
服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止。
2、自动间隔性保存
redis允许用户通过设置服务器的配置文件redis.conf文件中的save选项,让服务器每个一段时间自动执行一次bgsave命令。比如:
save 900 1
save 300 10
save 60 10000
表示:
服务器在900秒之内,对数据库进行了至少1次修改
服务器在300秒之内,对数据库进行了至少10次修改
服务器在60秒之内,对数据库进行了至少10000次修改
3、原理
服务器会根据save选项所设置的保存条件,设置服务器状态redisServer结构的saveparams属性,该属性是一个数组,,数组中每个元素都是一个saveparam结构,每个结构都保存了一个save选项设置的保存条件。
服务器状态还维持着一个dirty计数器,以及一个lastsave属性。
dirty计数器记录距离上一次成功执行save命令或者bgsave命令之后,服务器对数据库状态进行了多少次修改
lastsave属性是一个Unix时间戳,记录了服务器上一次成功执行save命令或者bgsave命令的时间。
二、RDB文件结构
1、RDB的数据结构
redis:长度为5字节,用于快速检查所载入的文件是否RDB文件
db_version:长度为4字节,记录了RDB文件的版本号
databases:包含零个或任意多个数据库,以及数据库中的键值对数据
EOF:常量的长度是1字节,标志着RDB文件正文内容结束
check_sum:是一个8字节的无符号整数,保存着一个校验和,是程序通过对REDIS、db_version、databases、EOF四部分的内容今次那个计算得出的。
2、databases部分:
databases数据库结构:
SELECTDB常量的长度是1字节,当读入程序遇到这个值的时候,它知道接下来要读入的将是一个数据库号码
db_number保存着一个数据库号码,根据号码的大小不同,这个部分的长度可以是1字节、2字节或者5字节。当程序读人db_number部分之后,服务器会调用SELECT命令,根
据读入的数据库号码进行数据库切换,使得之后读人的键值对可以载人到正确的数据库中。
key_value_pairs部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,那么过期时间也会和键值对保存在一起。根据键值对的数量、类型、内容以及是否有过期时间等条件的不同,key value pairs部分的长度也会有所不同。
3、key_value_pairs部分:
带过期时间的键值对:
不带过期时间的键值对:
4、value编码:
字符串对象
列表对象
集合对象
哈希对象
有序集合对象
intset编码的集合
RDB文件保存这种对象的方法是,先将整数集合转换为字符串对象,然后将这个字符串对象保存到RDB文件里面。
如果程序在读入RDB文件的过程中,碰到由整数集合对象转换成的字符串对象,那么程序会根据TYPE值的指示,先读入字符串对象,再将这个字符串对象转换成原来的整数集合对象。
ziplist编码的集合、哈希表或者有序集合
RDB文件保存这种对象的方法是:
1)将压缩列表转换成一个字符串对象。
2)将转换所得的字符串对象保存到RDB文件。
如果程序在读人RDB文件的过程中,碰到由压缩列表对象转换成的字符串对象,那么程序会根据TYPE值的指示,执行以下操作:
1)读人字符串对象,并将它转换成原来的压缩列表对象。
2)根据TYPE的值,设置压缩列表对象的类型:如果TYPE的值为REDIS_RDBTYPE LIST_ZIPLIST,那么压缩列表对象的类型为列表;如果TYPE的值为REDISRDB_TYPE_HASH_ZIPLIST,那么压缩列表对象的类型为哈希表;如果TYPE的值为REDIS_RDB_TYPE_ZSET_ZIPLIST,那么压缩列表对象的类型为有序集合。