RDB文件自动间隔性保存
- save配置项
- saveparam结构
- dirty计数器 和 lastsave属性
- 检查 是否满足 保存条件
- 自动触发RDB持久化的场景(重要!!!)
save配置项
因为BGSAVE
命令 可以在 不阻塞服务器进程的情况下执行,所以Redis允许 通过 设置 服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE
命令
用户可以通过 save选项 设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行BGSAVE
命令,例如:
save 900 1
save 300 10
save 60 10000
那么只要满足以下三个条件中的任意一个,BGSAVE
命令就会被执行:
- 服务器在900秒之内,对数据库进行了至少1次修改
- 服务器在300秒之内,对数据库进行了至少10次修改
- 服务器在60秒之内,对数据库进行了至少10000次修改
saveparam结构
当Redis服务器启动时,可以通过 指定配置文件 或者 传入启动参数的方式 设置 save选项,如果没有主动设置save选项,那么服务器会为save选项设置默认条件:
save 900 1
save 300 10
save 60 10000
接着,服务器程序 会根据 save选项 所设置的保存条件,设置服务器状态redisServer结构的saveparams
属性:
struct redisServer {
// ...
// 记录了保存条件的数组
struct saveparam *saveparams;
// ...
};
saveparams
属性是一个数组,数组中的每个元素都是一个saveparam
结构,每个saveparam
结构 都保存了一个 save选项 设置的 保存条件
struct saveparam {
// 秒数
time_t seconds;
// 修改数
int changes;
};
比如说,如果 save选项 的 值为以下条件:
save 900 1
save 300 10
save 60 10000
那么服务器状态中的saveparams
数组将会是如下情况:
dirty计数器 和 lastsave属性
- dirty计数器 记录(动词) 距离上一次成功执行
SAVE
命令 或者BGSAVE
命令之后,服务器 对 数据库状态(服务器中的所有数据库)进行了 多少次修改(包括写入、删除、更新等操作) -
lastsave
属性是一个UNIX时间戳,记录了 服务器 上一次成功执行SAVE
命令或者BGSAVE
命令的时间
struct redisServer {
// ...
// 修改计数器
long long dirty;
// 上一次执行保存的时间
time_t lastsave;
// ...
};
当服务器成功执行一个数据库修改命令之后,程序 就会对 dirty计数器 进行更新
命令修改了多少次数据库,dirty计数器的值就增加多
检查 是否满足 保存条件
Redis的服务器周期性操作函数serverCron
默认每隔100毫秒就会执行一次,该函数用于对正在运行的服务器进行维护,它的其中一项工作就是 检查 save选项 所设置的保存条件 是否已经满足,如果满足的话,就执行BGSAVE
命令
以下伪代码展示了serverCron
函数检查保存条件的过程:
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
数组中的所有保存条件,只要有任意一个条件被满足,那么服务器就会执行BGSAVE
命令
自动触发RDB持久化的场景(重要!!!)
- 使用save相关配置,如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave
- 如果 从节点 执行 全量复制操作,主节点自动执行bgsave生成RDB文件并发送给从节点
- 执行debug reload命令重新加载Redis时,也会自动触发save操作
- 默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave
- 执行flushall命令,本质上是触发了save配置条件