这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战
RDB持久化②自动间隔性保存
通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次BGSAVE命令,save选项可以设置多个保存条件,只要任意一个条件被满足,服务器就会执行BGSAVE命令。
通过save选项的设置,服务器保存在saveparams属性中,saveparams是个数组,每个saveparam结构都保存了一个save选项设置的保存条件
struct saveparam {
time_t seconds;
int changes;
};
服务器有一个dirty计数器和lastsave属性,dirty计数器用来记录距离上一次成功执行save命令或者BGSAVE命令后服务器对数据库进行了多少次修改,lastsave记录服务器中上一次成功执行save命令或者BGSAVE命令的时间。
当服务器成功执行数据库修改命令后,程序对dirty计数器进行更新,命令修改多少次数据库,dirty计数器的值就增加多少
redis的服务器周期性操作函数serverCron默认每隔100毫秒执行一次,用于维护正在运行的服务器,检查是否满足save保存的条件,如果满足,执行BGSAVE命令。
/* Check if a background saving or AOF rewrite in progress terminated. */
// 如果 BGSAVE 或者 BGREWRITEAOF 正在进行
// 那么检查它们是否已经执行完毕
if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) {
int statloc;
pid_t pid;
if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
int exitcode = WEXITSTATUS(statloc);
int bysignal = 0;
if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);
if (pid == server.rdb_child_pid) {
backgroundSaveDoneHandler(exitcode,bysignal);
} else if (pid == server.aof_child_pid) {
backgroundRewriteDoneHandler(exitcode,bysignal);
} else {
redisLog(REDIS_WARNING,
"Warning, detected child with unmatched pid: %ld",
(long)pid);
}
// 如果 BGSAVE 和 BGREWRITEAOF 都已经完成,那么重新开始 REHASH
updateDictResizePolicy();
}
} else {
/* If there is not a background saving/rewrite in progress check if
* we have to save/rewrite now */
// 如果有需要,开始 RDB 文件的保存
for (j = 0; j < server.saveparamslen; j++) {
struct saveparam *sp = server.saveparams+j;
if (server.dirty >= sp->changes &&
server.unixtime-server.lastsave > sp->seconds) {
redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...",
sp->changes, sp->seconds);
rdbSaveBackground(server.rdb_filename);
break;
}
}
/* Trigger an AOF rewrite if needed */
// 如果有需要,开始 AOF 文件重写
if (server.rdb_child_pid == -1 &&
server.aof_child_pid == -1 &&
server.aof_rewrite_perc &&
server.aof_current_size > server.aof_rewrite_min_size)
{
long long base = server.aof_rewrite_base_size ?
server.aof_rewrite_base_size : 1;
long long growth = (server.aof_current_size*100/base) - 100;
if (growth >= server.aof_rewrite_perc) {
redisLog(REDIS_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth);
rewriteAppendOnlyFileBackground();
}
}
}
这就是BGSAVE的实现原理