RDB持久化
RDB持久化
由于Redis是内存数据库,它将自己的数据库状态存储在内存里面,所以如果想要将Redis数据库中的数据存储下来,则必须要将内存中的数据持久化到硬盘中。
Redis提供了RDB和AOF两种持久化功能,我们今天先来介绍以下RDB持久化,这个功能可以将Redis在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。
RDB持久化既可以手动执行,也可以根据服务器配置定期执行,该功能可以将某个时间点的数据库状态保存到一个RDB文件中。
因为RDB文件是保存在硬盘中的,所以即使Redis服务器进程退出,甚至运行Redis服务器的计算机停机,但是只要RDB文件任然存在,Redis服务器就可以用它来还原数据库状态。
Redis服务器保存RDB文件的方法有SAVE和BGSAVE两个命令。
SAVE:
SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕,在服务器进程阻塞期间,服务器不能处理任何命令请求。
BGSAVE:
BGSAVE命令会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程(父进程)继续处理命令请求。
创建RDB文件的实际工作由rdb.c/rdbSave函数完成,SAVE命令和BGSAVE命令会以不同的方式调用这个函数,通过以下伪代码可以看出这两个命令的区别:
当服务器启动时,会从硬盘中找到对应的持久化文件进行初始化:
由于AOF文件的更新频率通常比RDB文件的更新频率高,所以如果服务器开启了AOF持久化,则会先使用AOF文件还原数据库状态。只有在AOF持久化功能关闭时,才会使用RDB文件来还原数据库状态。
SAVE命令在执行时,Redis服务器会被阻塞,所以当SAVE命令正在执行时,客户端发送的所有命令都会被拒绝。
只有在服务器执行完SAVE命令、重新开始接受命令请求之后,客户端发送的命令才会被处理。
BGSAVE命令的保存工作是由子进程执行的,所以在子进程创建RDB文件的过程中,Redis服务器任然可以继续处理客户端的命令其请求。
在BGSAVE命令执行期间,SAVE和BGSAVE命令会被拒绝,原因时同时执行会导致竞争。BGREWRITEAOF命令和BGSAVE两个命令不能同时执行。
BGREWRITEAOF和BGSAVE都是子进程执行,这两个操作并没有冲突的地方,凡是由于两个子进程会使用大量的磁盘读写资源,性能会受到一些影响,因此不这样使用。
服务器在载入RDB文件时,会一直处于阻塞状态,直到载入工作完成为止。
自动保存间隔
Redis默认由三种默认保存RDB文件的配置:
save 900 1
save 300 10
save 60 10000
只要满足以下三个条件中的一个,BGSAVE命令就会被执行:
900秒之内对数据库至少进行了1次修改
300秒之内对数据库至少进行了10修改
60秒之内对数据库至少进行了10000次修改
Redis使用saveparams保存BGSAVE配置信息:
使用dirty计数器和lastsave属性来判断是否需要执行BGSAVE操作,dirty记录了上次执行BGSAVE操作之后服务器对数据库状态执行了多少次修改,lastsave属性是一个UNIX时间戳,记录了上一次成功执行SAVE或BGSAVE命令的时间。
Redis服务器默认每隔100毫秒就执行一次serverCron函数,该甘薯用于对正在运行的Redis服务器进行维护,其中由一项工作就是检查save选项所设置的保存条件是否已满足,如果满足就执行BGSAVE命令。
程序会遍历saveparams数组中的所有条件,只要由一个条件满足,就执行BGSAVEv操作。
RDB文件结构
db_version长度为4字节,时一个字符串表示的整数,记录了RDB文件的版本号,"0006"表示RDB版本为第六版。
databases包含零个或者多个数据库以及数据库中的键值对数据。
databases结构
一个RDB文件的databases部分可以保存任意多个非空数据库
每个非空数据库在RDB文件中都可以保存以下三个部分:
SELECTDB是一个一字节的常量,标记后面将要读取一个数据库号码
db_number是一个一字节或者两字节或五字节的数据库号码
key_value_pairs部分保存了数据库中的所有键值对数据,如果键值对带有过期时间,则过期时间也会被保存。
总结: