异常断开引发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);
}