千哥说娱乐
当前位置:首页 - 视频 >

Redis RDB文件解析

2019-10-12来源:云浮汽车网

rdb文件是redis实现持久化方式的一种,即通过save或bgsave操作,执行数据备份,生成的.rdb后缀的数据文件。

save和bgsave都是调用rdbSave实现备份的,只不过save是阻塞式,bgsave是非阻塞式,通过fork子进程执行备份,主进程可以继续接收外部请求。源码如下:

一、save方法

直接调用rdbsave()方法

void saveCommand(client *c) {
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);
}
}

二、bgsave方法

调用的是rdbSaveBackground()方法

/* BGSAVE [SCHEDULE] */
void bgsaveCommand(client *c) {
int schedule = 0;
/* The SCHEDULE option changes the behavior of BGSAVE when an AOF rewrite
* is in progress. Instead of returning an error a BGSAVE gets scheduled. */
if (c->argc > 1) {
if (c->argc == 2 && !strcasecmp(c->argv[1]->ptr,"schedule")) {
schedule = 1;
} else {
addReply(c,shared.syntaxerr);
return;
}
}
rdbSaveInfo rsi, *rsiptr;
rsiptr = rdbPopulateSaveInfo(&rsi);
if (server.rdb_child_pid != -1) {
addReplyError(c,"Background save already in progress");
} else if (server.aof_child_pid != -1) {
if (schedule) {
server.rdb_bgsave_scheduled = 1;
addReplyStatus(c,"Background saving scheduled");
} else {
addReplyError(c,
"An AOF log rewriting in progress: can't BGSAVE right now. "
"Use BGSAVE SCHEDULE in order to schedule a BGSAVE whenever "
"possible.");
}
} else if (rdbSaveBackground(server.rdb_filename,rsiptr) == C_OK) { #实际上调用的是rdbSaveBackground方法
addReplyStatus(c,"Background saving started");
} else {
addReply(c,shared.err);
}
}

三、rdbSaveBackground方法

int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) {
pid_t childpid;
long long start;
if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;
server.dirty_before_bgsave = server.dirty;
server.lastbgsave_try = time(NULL);
openChildInfoPipe();
start = ustime();
if ((childpid = fork()) == 0) {
int retval;
/* Child */
closeListeningSockets(0);
redisSetProcTitle("redis-rdb-bgsave");
retval = rdbSave(filename,rsi); # 最终调用的还是rdbsave()方法,但是是在子进程中调用的
if (retval == C_OK) {
size_t private_dirty = zmalloc_get_private_dirty(-1);
if (private_dirty) {
serverLog(LL_NOTICE,
"RDB: %zu MB of memory used by copy-on-write",
private_dirty/(1024*1024));
}
server.child_info_data.cow_size = private_dirty;
sendChildInfo(CHILD_INFO_TYPE_RDB);
}
exitFromChild((retval == C_OK) ? 0 : 1);
} else {
/* Parent */
server.stat_fork_time = ustime()-start;
server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */
latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000);
if (childpid == -1) {
closeChildInfoPipe();
server.lastbgsave_status = C_ERR;
serverLog(LL_WARNING,"Can't save in background: fork: %s",
strerror(errno));
return C_ERR;
}
serverLog(LL_NOTICE,"Background saving started by pid %d",childpid);
server.rdb_save_time_start = time(NULL);
server.rdb_child_pid = childpid;
server.rdb_child_type = RDB_CHILD_TYPE_DISK;
updateDictResizePolicy();
return C_OK;
}
return C_OK; /* unreached */
}

在了解rdb文件是怎么生成后,接下来就看看rdb文件内容,rdb文件是二进制格式的,直接打开是乱码,可以使用命令 od -c xxx.rdb 查看

四、RDB文件内容解析

本地先安装redis吧(此处省略)

由于是之前安装好的,此处执行flushall命令情况redis数据库

Redis RDB文件解析

接下来执行save,默认是dump.rdb文件,文件名在redis.window.conf里配置,

conf文件配置

# The filename where to dump the DB
dbfilename dump.rdb

使用od -c 查看

Redis RDB文件解析

RDB文件结构包括REDIS、rdb_version、databases、EOF以及check_sum,databases部分包含SELECTDB、db_number、key_value_pairs,如下图:

Redis RDB文件解析

Redis RDB文件解析

其中:
REDIS:是证明rdb文件,5字节
0006:版本号,1字节
377:EOF,
377之后的是checknum
因为无数据,所以也没有databases信息

再看一个有数据的rdb文件

Redis RDB文件解析

其中:
REDIS:是证明rdb文件,5字节
0006:版本号,1字节
376:SELECTDB
\0:0号数据库,默认有16个数据库,总数可在配置中修改,databases 16
\0:是数据类型type,0是string
004:数据长度
name:是字符串key
004:值长度
jack:key的值
377:EOF
377后面的是checknum
转载文章地址:http://www.xxglsh.com/shipin/49477.html
(本文来自千哥说娱乐整合文章:http://www.xxglsh.com)未经允许,不得转载!
标签:
网站简介 联系我们 网站申明 网站地图

版权所有:www.xxglsh.com ©2017 千哥说娱乐

千哥说娱乐提供的所有内容均是网络转载或网友提供,本站仅提供内容展示服务,不承认任何法律责任。