我们知道Redis的数据库数据是储存在内存中的,那么如果Redis服务器进程被kill了或关闭了,那么服务器中的所有数据都会消失,所以我们需要对Redis的数据进行持久化即保存在硬盘中。
Redis有两种持久化的方案——RDB和AOF(Append OnlyFile)。
一、RDB持久化
RDB持久化通过将数据库中的键值对保存到rdb文件中来对Redis进行备份。src下的rdb.c和rdb.h包含了对RDB文件的一些定义及操作。
1.RDB文件的生成
Redis可以用SAVE或者BGSAVE命令生成RDB文件:
void saveCommand(redisClient *c) {
//BGSAVE 已经在执行中,不能再执行 SAVE
// 否则将产生竞争条件
if(server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
return;
}
// 执行
if(rdbSave(server.rdb_filename) == REDIS_OK) {
addReply(c,shared.ok);
} else{
addReply(c,shared.err);
}
}
void bgsaveCommand(redisClient *c) {
// 不能重复执行 BGSAVE
if(server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
// 不能在 BGREWRITEAOF 正在运行时执行
} elseif (server.aof_child_pid != -1) {
addReplyError(c,"Can't BGSAVE while AOF log rewriting is inprogress");
// 执行 BGSAVE
} elseif (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {
addReplyStatus(c,"Background saving started");
} else{
addReply(c,shared.err);
}
}
其中SAVE命令底层通过rdbSave函数实现;BGSAVE命令底层通过rdbSaveBackground函数实现。然而事实上,rdbSaveBackground底层也调用了rdbSave函数来实现。
从这两个函数的命名我们就能看出来BGSAVE调用的rdbSaveBackground函数是在后台进行RDB文件的创建的——实际实现中,Redis会创建一个子进程来进行RDB文件的创建,而父进程继续处理命令请求,这样就不会导致在RDB文件创建的过程中阻塞其他的命令请求。而SAVE命令是会阻塞命令请求直至完成SAVE命令。因此Redis一般情况下都是执行BGSAVE命令。