Redis源码小记

异常断开引发Full Sync

日志如下:

18030:S 13 Feb 15:53:46.700 - Protocol error from client: id=7 addr=keeper-addr fd=6 name= age=1224339 idle=0 flags=M db=0 sub=0 psub=0 multi=-1 qbuf=720 qbuf-free=32048 obl=0 oll=0 omem=0 events=r cmd=set
18030:S 13 Feb 15:53:47.457 # Connection with master lost.
18030:S 13 Feb 15:53:48.458 * Connecting to MASTER keeper-addr
18030:S 13 Feb 15:53:48.459 * MASTER <-> SLAVE sync started
18030:S 13 Feb 15:53:48.459 * Non blocking connect for SYNC fired the event.
18030:S 13 Feb 15:53:48.461 * Master replied to PING, replication can continue...
18030:S 13 Feb 15:53:48.463 * Partial resynchronization not possible (no cached master)
18030:S 13 Feb 15:54:35.681 * Full resync from master: 342575b0c5bcefc1fc8230d435287217ecb29dc9:105751796725

发现Redis对于异常逻辑中, 会有特殊处理
network.c中, 有如下代码:

static void setProtocolError(const char *errstr, client *c, long pos) {
    if (server.verbosity <= LL_VERBOSE) {
        sds client = catClientInfoString(sdsempty(),c);

        /* Sample some protocol to given an idea about what was inside. */
        char buf[256];
        if (sdslen(c->querybuf) < PROTO_DUMP_LEN) {
            snprintf(buf,sizeof(buf),"Query buffer during protocol error: '%s'", c->querybuf);
        } else {
            snprintf(buf,sizeof(buf),"Query buffer during protocol error: '%.*s' (... more %zu bytes ...) '%.*s'", PROTO_DUMP_LEN/2, c->querybuf, sdslen(c->querybuf)-PROTO_DUMP_LEN, PROTO_DUMP_LEN/2, c->querybuf+sdslen(c->querybuf)-PROTO_DUMP_LEN/2);
        }

        /* Remove non printable chars. */
        char *p = buf;
        while (*p != '\0') {
            if (!isprint(*p)) *p = '.';
            p++;
        }

        /* Log all the client and protocol info. */
        serverLog(LL_VERBOSE,
            "Protocol error (%s) from client: %s. %s", errstr, client, buf);
        sdsfree(client);
    }
    c->flags |= CLIENT_CLOSE_AFTER_REPLY;
    sdsrange(c->querybuf,pos,-1);
}

最后几行, 有设置标签 c->flags |= CLIENT_CLOSE_AFTER_REPLY;

然后, 在networking.c中的 freeClient(client *c)中, 对释放的 client 有逻辑判断:
如果说, client 是 master, 并且 client 有如下几个情况的, 则不会 cache master, 导致在后文中没有 cached master 而引发的 FULL SYNC

/* If it is our master that's beging disconnected we should make sure
     * to cache the state to try a partial resynchronization later.
     *
     * Note that before doing this we make sure that the client is not in
     * some unexpected state, by checking its flags. */
    if (server.master && c->flags & CLIENT_MASTER) {
        serverLog(LL_WARNING,"Connection with master lost.");
        if (!(c->flags & (CLIENT_CLOSE_AFTER_REPLY|
                          CLIENT_CLOSE_ASAP|
                          CLIENT_BLOCKED|
                          CLIENT_UNBLOCKED)))
        {
            replicationCacheMaster(c);
            return;
        }
    }

replication.c 中, slaveTryPartialResynchronization(int fd, int read_reply)中关于是否全量同步的判定:

 if (server.cached_master) {
            psync_replid = server.cached_master->replid;
            snprintf(psync_offset,sizeof(psync_offset),"%lld", server.cached_master->reploff+1);
            serverLog(LL_NOTICE,"Trying a partial resynchronization (request %s:%s).", psync_replid, psync_offset);
        } else {
            serverLog(LL_NOTICE,"Partial resynchronization not possible (no cached master)");
            psync_replid = "?";
            memcpy(psync_offset,"-1",3);
        }

你可能感兴趣的:(Redis源码小记)