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.
This commit is contained in:
zhaozhao.zz 2017-09-20 13:47:42 +08:00 committed by antirez
parent 097a555677
commit f119464929
4 changed files with 33 additions and 9 deletions

View File

@ -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++;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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