我知道点redis-单机数据库(RDB持久化)
10.1 RDB文件的创建和载入
有两个Redis命令可以用于生成RDB文件,一个是SAVE
,另一个是BGSAVE
。
10.1.1 创建
SAVE
SAVE
命令会阻塞Redis服务器进程,直到RDB文件创建完毕,在服务器进程阻塞期间,服务器不能处理任何请求。
BGSAVE
BGSAVE
命令会派生一个subprocess,然后由子进程负责创建RDB文件,父进程继续处理命令请求。
因为BGSAVE
命令的保存工作是由subprocess执行的,所以在subprocess创建RDB file的过程中,Redis server仍然可以继续处理client的命令请求。但是在BGSAVE
命令执行期间,server处理SAVE
、BGSAVE
、BGREWRITEAOF
三个命令的方式会和平时有所不同。
- 首先,在
BGSAVE
命令执行期间,SAVE
和BGSAVE
命令将被reject。 - 其次,在
BGSAVE
命令执行期间,BGREWRITEAOF
和BGSAVE
两个命令不能同时执行。
10.1.2 载入
RDB文件的载入工作是在服务器启动时自动执行的,所以Redis没有专门用于载入RDB文件的命令。
另外,值得一提的是,因为AOF文件的更新频率通常比RDB文件的更新频率高,所以:
- 如果服务器开启了AOF持久化功能,那么server会优先使用AOF file来reduction db status;
- 只有在AOF 持久化功能处于close状态时,server才会使用RDB file 来 reduction db status。
10.2 自动间隔性保存
因为BGSAVE
命令可以在不阻塞server process的情况下执行,所以Redis允许用户通过设置server配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE
则不会。
user可以通过save选项设置多个保存条件,但只要其中任意一个条件被满足,server就会执行BGSAVE
命令。
save 900 1
表示服务器在900s内,对db进行了至少1次就修改。
10.2.1 设置保存条件
当Redis server启动时,用户可以通过指定配置文件或者传入启动参数的方式配置save选项。server根据save选项所设置的保存条件,设置server状态redisServer
的saveparams
属性:
struct redisServer {
// ...
// 记录保存条件的数组
struct saveparam *saveparams;
// ...
}
saveparams
属性是个数组,数组中的每个元素都是一个saveparam
结构,每个saveparam
结构都保存了一个save选项设置的保存条件:
struct saveparam {
// 秒数
time_t seconds;
// 修改数
int changes;
}
10.2.2 dirty
计数器和lastsave
属性
除了saveparams
数组之外,服务器状态还维持着一个dirty
计数器,以及一个lastsave
属性:
-
dirty
计数器记录着距离上一次成功SAVE
命令或者BGSAVE
命令之后,服务器对db status进行了多少次修改。 -
lastsave
属性属于一个UNIX时间戳,记录了服务次上一次成功执行SAVE
命令或者BGSAVE
命令的时间.
code
struct redisServer {
// ...
// 修改计数器
long long dirty;
// 上一次执行保存的时间
time_t lastsave;
// ...
}
当Server成功执行一次db修改命令,dirty
就会更新:命令修改了多少次db,dirty
值就是多少。
10.2.3 检查保存条件是否满足
Redis的服务器周期性操作函数serverCron
默认每隔100ms就会执行一次,该函数用于对正在运行的server进行维护,它的其中一项工作就是检查save现象所设置的保存条件是否已经满足,如果满足的话,就执行BGSAVE命令。
// 伪代码
def serverCron() :
# ...
# 遍历所有保存条件
for saveparam in server.saveparams:
# 计算距离上次执行保存操作有多少秒
save_interval = unixtime_now() - server.lastsave
# 如果数据库状态的修改次数超过条件所设置的次数
# 并且距离上次保存的时间超过条件所设置的时间
# 那么执行保存操作
if server.dirty >= saveparam.changes and \
save_interval > saveparam.seconds:
BGSAVE()
# ...
程序会遍历病检查saveparams
数组中的所有保存条件,只要有任意一个条件被满足,那么server就会执行BGSAVE
命令。
以上就是Redis server根据save选项所设置的保存条件,自动执行BGSAVE
命令,进行间隔性数据保存的实现原理。