redis是内存数据库,如果数据没有写入磁盘,一旦服务器挂掉或者进程退出,那么数据也就不见了。
redis通过将数据保存到一个RDB文件中来实现持久化。
RDB文件是一个经过压缩的二进制文件,保存在硬盘上,这样即便是服务器挂掉或者进程退出,数据也不会丢失。在服务器启动时会载入RDB文件。
先来看看创建RDB文件
redis提供了两种命令来创建RDB文件:SAVE命令和BGSAVE命令。
SAVE
客户端输入SAVE命令
void saveCommand(client *c) {
/* 判断是否已经有bgsave操作 */
if (server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
return;
}
rdbSaveInfo rsi, *rsiptr;
rsiptr = rdbPopulateSaveInfo(&rsi);
if (rdbSave(server.rdb_filename,rsiptr) == C_OK) {
addReply(c,shared.ok);
} else {
addReply(c,shared.err);
}
}
这里关注rdbSave方法,就是SAVE命令的具体实现:
int rdbSave(char *filename, rdbSaveInfo *rsi) {
char tmpfile[256];
char cwd[MAXPATHLEN]; /* 存放错误信息 */
FILE *fp;
rio rdb;
int error = 0;
snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
fp = fopen(tmpfile,"w"); /* 调用函数库的fopen函数,创建(打开)只写文件 */
if (!fp) {/* 创建(打开)失败 */
char *cwdp = getcwd(cwd,MAXPATHLEN);
serverLog(LL_WARNING,
"Failed opening the RDB file %s (in server root dir %s) "
"for saving: %s",
filename,
cwdp ? cwdp : "unknown",
strerror(errno));
return C_ERR;
}
/* 初始化文件 */
rioInitWithFile(&rdb,fp);
/* 以RDB格式生成数据库转储文件,并将其发送到指定的Redis I/O通道 */
if (rdbSaveRio(&rdb,&error,RDB_SAVE_NONE,rsi) == C_ERR) {
errno = error;
goto werr;
}
/* 确保数据不会留在操作系统的输出缓冲区中 */
if (fflush(fp) == EOF)