From b541ccef25d20749c739b858ef8694512b7f3bce Mon Sep 17 00:00:00 2001 From: "zhaozhao.zz" Date: Wed, 20 Sep 2017 13:47:42 +0800 Subject: [PATCH] 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. --- src/db.c | 4 +++- src/debug.c | 4 +++- src/rdb.c | 20 +++++++++++++++++--- src/replication.c | 14 ++++++++++---- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/db.c b/src/db.c index 7d1504d3..71c642d0 100644 --- a/src/db.c +++ b/src/db.c @@ -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 d6e12ec2..5c3fd347 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; } diff --git a/src/rdb.c b/src/rdb.c index 9c2acf7b..c83a05a3 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -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 2b2673a4..4358d63e 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