1、 redis数据同步分析
在(13)中我们分析到了真正与主服务器进行交互的方法是syncWithMaster方法,这里我们就开始详细分析这个方法,首先是代码前面的部分,如下图所示:
这里的重点在1659行,前面的是一些赋值操作和异常或退出操作的处理,这里不详细分析了,1659行的if条件会根据server.repl_state的值来判断是否执行,在(13)中我们提到connectWithMaster方法在最后会将这个参数的值改为REPL_STATE_CONNECTING,所以这个if条件会被执行。
从注释上来看这段if语句主要的作用在于向主服务器发送一个ping命令,调用的方法是sendSynchronousCommand方法在1667行,命令被设置为了“PING”,同时还需要注意在上面1664行,server.repl_state的值被改为了REPL_STATE_RECEIVE_PONG。
sendSynchronousCommand方法,主要目的是将命令通过socket发送给主服务器,其具体内容如下:
/* Send a synchronous command to the master. Used to send AUTH and
* REPLCONF commands before starting the replication with SYNC.
*
* The command returns an sds string representing the result of the
* operation. On error the first byte is a "-".
*/
#define SYNC_CMD_READ (1<<0)
#define SYNC_CMD_WRITE (1<<1)
#define SYNC_CMD_FULL (SYNC_CMD_READ|SYNC_CMD_WRITE)
char *sendSynchronousCommand(int flags, int fd, ...) {
/* Create the command to send to the master, we use redis binary
* protocol to make sure correct arguments are sent. This function
* is not safe for all binary data. */
if (flags & SYNC_CMD_WRITE) {
char *arg;
va_list ap;
sds cmd = sdsempty();
sds cmdargs = sdsempty();
size_t argslen = 0;
va_start(ap,fd);
while(1) {
arg = va_arg(ap, char*);
if (arg == NULL) break;
cmdargs = sdscatprintf(cmdargs,"$%zu\r\n%s\r\n",strlen(arg),arg);
argslen++;
}
va_end(ap);
cmd = sdscatprintf(cmd,"*%zu\r\n",argslen);
cmd = sdscatsds(cmd,cmdargs);
sdsfree(cmdargs);
/* Transfer command to the server. */
if (syncWrite(fd,cmd,sdslen(cmd),server.repl_syncio_timeout*1000)
== -1)
{
sdsfree(cmd);
return sdscatprintf(sdsempty(),"-Writing to master: %s",
strerror(errno));
}
sdsfree(cmd);
}
/* Read the reply from the server. */
if (flags & SYNC_CMD_READ) {
char buf[256];
if (syncReadLine(fd,buf,sizeof(buf),server.repl_syncio_timeout*1000)
== -1)
{
return sdscatprintf(sdsempty(),"-Reading from master: %s",
strerror(errno));
}
server.repl_transfer_lastio = server.unixtime;
return sdsnew(buf);
}
return NULL;
}
到这这里从服务器这边的操作便可以算是告一段落了,从之前的分析我们可以知道,在从服务器接收到slaveof命令后,它会使用socket与主服务器进行连接,连接成功后会向主服务器发送一个ping命令。
接下来就应该分析主服务器这边在接收到ping命令后的操作了,不过在分析这个之前,需要先分析redis怎么从socket中读取命令并执行的。这个首先要从redis的启动开始分析。