Redis集群分析(4)

it2026-03-09  2

1、 redis源码介绍

在(3)中详细介绍了redis的几种持久化模式,接下来就在redis的源码中介绍,其持久化的实现方式。 在详细介绍其代码之前先简单介绍一下redis源码的目录结构。

在官网下载的文件解压后可以得到以下目录:

源码在src目录中,其内容如下:

文件很多,有一百多个,其中与持久化相关的有server.c、aof.c、rdb.c等等。

2、 RDB源码

代码入口

从之前的分析可以知道redis触发RDB的持久化有两种方式,一种是满足save命令设定的条件,还有一种是在客户端输入bgsave命令。

第一种是根据条件触发的,作为读源码的入口来说不是很合适,第二种需要解析客户端与服务器的交互,服务器接收到命令的命令解析过程,然后才是命令的执行。

这里我们首先分析第二种方式,不过我们略过前面的步骤,直接从bgsave的命令执行开始。

首先我们在src目录下找到server.c文件(本文使用的5.0版本,早期版本可能没有这个文件,类似的文件可以找redis.c),在这个文件中定义的一个redisCommandTable数组,这个数组里定义的redis支持的命令与其对应函数的对应关系,在其中找到bgsave命令。如图:

从这里可以看出在执行bgsave命令的时候实际是会执行bgsaveCommand函数,这个函数我们可以在rdb.c中找到,其内容如下:

/* 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) { addReplyStatus(c,"Background saving started"); } else { addReply(c,shared.err); } }

仔细分析上述代码会发现:他实际没有执行持久化操作,他只是将 server.rdb_bgsave_scheduled的值设置为1了。其他的代码都打印错误信息之类的。那么bgsave的执行方式就很明显了,他只是更改rdb_bgsave_scheduled的值,然后快速返回,告诉用bgsave已经开始,最后数据库读取到这个值再开始执行持久化。

最新回复(0)