Redis集群分析(12)

1、 redis的主从数据同步源码分析

在(11)中我们分析了主从服务器间的数据同步机制,这里我们接着从源码的角度来继续分析其数据同步。

主从服务器的数据同步,我们依然从最基础的slaveof命令开始分析。首先假设我们有两台服务器A与B,我们要用A作为主服务器,B作为从服务器。这时只需要用客户端连接到B,然后输入slaveof加上A的ip与端口便可。

B在收到命令后,会按正常的命令执行流程来执行该命令,如同之前的命令一样,可以在server.c中可以找该命令与其对应的方法,如下图:

在这里插入图片描述

可以看见与slaveof命令对应的是一个叫replicaofCommand的方法,这个方法实现在replication.c文件中,其实现内容如下:

void replicaofCommand(client *c) {
    /* SLAVEOF is not allowed in cluster mode as replication is automatically
     * configured using the current address of the master node. */
    if (server.cluster_enabled) {
        addReplyError(c,"REPLICAOF not allowed in cluster mode.");
        return;
    }

    /* The special host/port combination "NO" "ONE" turns the instance
     * into a master. Otherwise the new master address is set. */
    if (!strcasecmp(c->argv[1]->ptr,"no") &&
        !strcasecmp(c->argv[2]->ptr,"one")) {
        if (server.masterhost) {
            replicationUnsetMaster();
            sds client = catClientInfoString(sdsempty(),c);
            serverLog(LL_NOTICE,"MASTER MODE enabled (user request from '%s')",
                client);
            sdsfree(client);
        }
    } else {
        long port;

        if (c->flags & CLIENT_SLAVE)
        {
            /* If a client is already a replica they cannot run this command,
             * because it involves flushing all replicas (including this
             * client) */
            addReplyError(c, "Command is not valid when client is a replica.");
            return;
        }

        if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != C_OK))
            return;

        /* Check if we are already attached to the specified slave */
        if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr)
            && server.masterport == port) {
            serverLog(LL_NOTICE,"REPLICAOF would result into synchronization with the master we are already connected with. No operation performed.");
            addReplySds(c,sdsnew("+OK Already connected to specified master\r\n"));
            return;
        }
        /* There was no previous master or the user specified a different one,
         * we can continue. */
        replicationSetMaster(c->argv[1]->ptr, port);
        sds client = catClientInfoString(sdsempty(),c);
        serverLog(LL_NOTICE,"REPLICAOF %s:%d enabled (user request from '%s')",
            server.masterhost, server.masterport, client);
        sdsfree(client);
    }
    addReply(c,shared.ok);
}

这个方法的重点在第11行,这是一个if else语句,当slaveof命令后面添加的参数是no one的时候,if条件成立,表示从服务器将不在作为从服务器同步指定的主服务器。这个在哨兵模式下,哨兵发现主服务器故障后,更换主服务器的时候会用到。

然后是else语句,这里有一大堆if语句检查服务器状态,最重要的是在第44行,执行了一个replicationSetMaster方法,这个方法将传入的ip与端口的redis设置为主服务器。其具体内容如下:

/* Set replication to the specified master address and port. */
void replicationSetMaster(char *ip, int port) {
    int was_master = server.masterhost == NULL;

    sdsfree(server.masterhost);
    server.masterhost = sdsnew(ip);
    server.masterport = port;
    if (server.master) {
        freeClient(server.master);
    }
    disconnectAllBlockedClients(); /* Clients blocked in master, now slave. */

    /* Force our slaves to resync with us as well. They may hopefully be able
     * to partially resync with us, but we can notify the replid change. */
    disconnectSlaves();
    cancelReplicationHandshake();
    /* Before destroying our master state, create a cached master using
     * our own parameters, to later PSYNC with the new master. */
    if (was_master) {
        replicationDiscardCachedMaster();
        replicationCacheMasterUsingMyself();
    }
    server.repl_state = REPL_STATE_CONNECT;
}

这段代码最重要的地方在第6行、第7行和第23行,这几处为几个重要的参数进行了赋值。第6、7行记录了主服务的ip与端口,第23行标识了从服务器下一阶段需要去连接主服务器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值