diff options
author | zhaozhao.zz <zhaozhao.zz@alibaba-inc.com> | 2017-09-20 13:47:42 +0800 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2017-09-20 11:18:10 +0200 |
commit | b541ccef25d20749c739b858ef8694512b7f3bce (patch) | |
tree | e99ef1b6889ce2b4f2f9d4784a777e26bc2439a1 | |
parent | c1c99e9f4e19b3c68d810a51449b34c2261e24c9 (diff) | |
download | redis-b541ccef25d20749c739b858ef8694512b7f3bce.tar.gz |
PSYNC2: make persisiting replication info more solid
This commit is a reinforcement of commit c1c99e9.
1. Replication information can be stored when the RDB file is
generated by a mater using server.slaveseldb when server.repl_backlog
is not NULL, or set repl_stream_db be -1. That's safe, because
NULL server.repl_backlog will trigger full synchronization,
then master will send SELECT command to replicaiton stream.
2. Only do rdbSave* when rsiptr is not NULL,
if we do rdbSave* without rdbSaveInfo, slave will miss repl-stream-db.
3. Save the replication informations also in the case of
SAVE command, FLUSHALL command and DEBUG reload.
-rw-r--r-- | src/db.c | 4 | ||||
-rw-r--r-- | src/debug.c | 4 | ||||
-rw-r--r-- | src/rdb.c | 20 | ||||
-rw-r--r-- | src/replication.c | 14 |
4 files changed, 33 insertions, 9 deletions
@@ -416,7 +416,9 @@ void flushallCommand(client *c) { /* Normally rdbSave() will reset dirty, but we don't want this here * as otherwise FLUSHALL will not be replicated nor put into the AOF. */ int saved_dirty = server.dirty; - rdbSave(server.rdb_filename,NULL); + rdbSaveInfo rsi, *rsiptr; + rsiptr = rdbPopulateSaveInfo(&rsi); + rdbSave(server.rdb_filename,rsiptr); server.dirty = saved_dirty; } server.dirty++; diff --git a/src/debug.c b/src/debug.c index d6e12ec2a..5c3fd3471 100644 --- a/src/debug.c +++ b/src/debug.c @@ -335,7 +335,9 @@ void debugCommand(client *c) { if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]); serverAssertWithInfo(c,c->argv[0],1 == 2); } else if (!strcasecmp(c->argv[1]->ptr,"reload")) { - if (rdbSave(server.rdb_filename,NULL) != C_OK) { + rdbSaveInfo rsi, *rsiptr; + rsiptr = rdbPopulateSaveInfo(&rsi); + if (rdbSave(server.rdb_filename,rsiptr) != C_OK) { addReply(c,shared.err); return; } @@ -1975,7 +1975,9 @@ void saveCommand(client *c) { addReplyError(c,"Background save already in progress"); return; } - if (rdbSave(server.rdb_filename,NULL) == C_OK) { + rdbSaveInfo rsi, *rsiptr; + rsiptr = rdbPopulateSaveInfo(&rsi); + if (rdbSave(server.rdb_filename,rsiptr) == C_OK) { addReply(c,shared.ok); } else { addReply(c,shared.err); @@ -2017,21 +2019,33 @@ void bgsaveCommand(client *c) { } /* Populate the rdbSaveInfo structure used to persist the replication - * information inside the RDB file. Currently the structure explicitly + * information inside the RDB file. + * For master, if server.repl_backlog is not NULL, fill rdbSaveInfo with + * server.slaveseldb, otherwise just use init -1. + * Don't worry, master will send SELECT command to replication stream, + * because if server.repl_backlog is NULL, that will trigger full synchronization, + * function replicationSetupSlaveForFullResync() sets server.slaveseldb be -1, + * then replicationFeedSlaves() will send SELECT command when server.slaveseldb is -1. + * For slave, currently the structure explicitly * contains just the currently selected DB from the master stream, however * if the rdbSave*() family functions receive a NULL rsi structure also * the Replication ID/offset is not saved. The function popultes 'rsi' * that is normally stack-allocated in the caller, returns the populated * pointer if the instance has a valid master client, otherwise NULL - * is returned, and the RDB savign wil not persist any replication related + * is returned, and the RDB saving will not persist any replication related * information. */ rdbSaveInfo *rdbPopulateSaveInfo(rdbSaveInfo *rsi) { rdbSaveInfo rsi_init = RDB_SAVE_INFO_INIT; *rsi = rsi_init; + if (!server.masterhost) { + if (server.repl_backlog) rsi->repl_stream_db = server.slaveseldb; + return rsi; + } if (server.master) { rsi->repl_stream_db = server.master->db->id; return rsi; } else { + serverLog(LL_WARNING,"As a slave there is no valid master, can not persist replication information"); return NULL; } } diff --git a/src/replication.c b/src/replication.c index 2b2673a4b..4358d63e6 100644 --- a/src/replication.c +++ b/src/replication.c @@ -571,10 +571,16 @@ int startBgsaveForReplication(int mincapa) { rdbSaveInfo rsi, *rsiptr; rsiptr = rdbPopulateSaveInfo(&rsi); - if (socket_target) - retval = rdbSaveToSlavesSockets(rsiptr); - else - retval = rdbSaveBackground(server.rdb_filename,rsiptr); + /* Only do rdbSave* when rsiptr is not NULL, + * otherwise slave will miss repl-stream-db. */ + if (rsiptr) { + if (socket_target) + retval = rdbSaveToSlavesSockets(rsiptr); + else + retval = rdbSaveBackground(server.rdb_filename,rsiptr); + } else { + retval = C_ERR; + } /* If we failed to BGSAVE, remove the slaves waiting for a full * resynchorinization from the list of salves, inform them with |