From 269233913800a51bdc0ef3eba6de1da13107b8fc Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 12 May 2014 16:34:20 +0200 Subject: [PATCH] Cluster: forced failover implemented. Using CLUSTER FAILOVER FORCE it is now possible to failover a master in a forced way, which means: 1) No check to understand if the master is up is performed. 2) No data age of the slave is checked. Evan a slave with very old data can manually failover a master in this way. 3) No chat with the master is attempted to reach its replication offset: the master can just be down. --- src/cluster.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 70ad7ab7..6ce6a3d1 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -3646,13 +3646,27 @@ void clusterCommand(redisClient *c) { addReplyBulkCString(c,ni); sdsfree(ni); } - } else if (!strcasecmp(c->argv[1]->ptr,"failover") && c->argc == 2) { - /* CLUSTER FAILOVER */ + } else if (!strcasecmp(c->argv[1]->ptr,"failover") && + (c->argc == 2 || c->argc == 3)) + { + /* CLUSTER FAILOVER [FORCE] */ + int force = 0; + + if (c->argc == 3) { + if (!strcasecmp(c->argv[2]->ptr,"force")) { + force = 1; + } else { + addReply(c,shared.syntaxerr); + return; + } + } + if (nodeIsMaster(myself)) { addReplyError(c,"You should send CLUSTER FAILOVER to a slave"); return; - } else if (myself->slaveof == NULL || nodeFailed(myself->slaveof) || - myself->slaveof->link == NULL) + } else if (!force && + (myself->slaveof == NULL || nodeFailed(myself->slaveof) || + myself->slaveof->link == NULL)) { addReplyError(c,"Master is down or failed, " "please use CLUSTER FAILOVER FORCE"); @@ -3660,7 +3674,15 @@ void clusterCommand(redisClient *c) { } resetManualFailover(); server.cluster->mf_end = mstime() + REDIS_CLUSTER_MF_TIMEOUT; - clusterSendMFStart(myself->slaveof); + + /* If this is a forced failover, we don't need to talk with our master + * to agree about the offset. We just failover taking over it without + * coordination. */ + if (force) { + server.cluster->mf_can_start = 1; + } else { + clusterSendMFStart(myself->slaveof); + } redisLog(REDIS_WARNING,"Manual failover user request accepted."); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"set-config-epoch") && c->argc == 3)