summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2015-03-20 17:55:22 +0100
committerantirez <antirez@gmail.com>2015-03-20 17:56:21 +0100
commita7010ae20813658c5cd3b6f1a6651ec5cb0909e2 (patch)
treef1f1cd7c703a054e7a073e78106ea56e4143a5a9
parent230d14142032bd054efceab21801068b5aa8a330 (diff)
downloadredis-a7010ae20813658c5cd3b6f1a6651ec5cb0909e2.tar.gz
Cluster: non-conditional steps of slave failover refactored into a function.
-rw-r--r--src/cluster.c67
1 files changed, 40 insertions, 27 deletions
diff --git a/src/cluster.c b/src/cluster.c
index 74468cfae..4f445f5d7 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -2636,6 +2636,42 @@ void clusterLogCantFailover(int reason) {
redisLog(REDIS_WARNING,"Currently unable to failover: %s", msg);
}
+/* This function implements the final part of automatic and manual failovers,
+ * where the slave grabs its master's hash slots, and propagates the new
+ * configuration.
+ *
+ * Note that it's up to the caller to be sure that the node got a new
+ * configuration epoch already. */
+void clusterFailoverReplaceYourMaster(void) {
+ int j;
+ clusterNode *oldmaster = myself->slaveof;
+
+ if (nodeIsMaster(myself) || oldmaster == NULL) return;
+
+ /* 1) Turn this node into a master. */
+ clusterSetNodeAsMaster(myself);
+ replicationUnsetMaster();
+
+ /* 2) Claim all the slots assigned to our master. */
+ for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
+ if (clusterNodeGetSlotBit(oldmaster,j)) {
+ clusterDelSlot(j);
+ clusterAddSlot(myself,j);
+ }
+ }
+
+ /* 3) Update state and save config. */
+ clusterUpdateState();
+ clusterSaveConfigOrDie(1);
+
+ /* 4) Pong all the other nodes so that they can update the state
+ * accordingly and detect that we switched to master role. */
+ clusterBroadcastPong(CLUSTER_BROADCAST_ALL);
+
+ /* 5) If there was a manual failover in progress, clear the state. */
+ resetManualFailover();
+}
+
/* This function is called if we are a slave node and our master serving
* a non-zero amount of hash slots is in FAIL state.
*
@@ -2650,7 +2686,6 @@ void clusterHandleSlaveFailover(void) {
int needed_quorum = (server.cluster->size / 2) + 1;
int manual_failover = server.cluster->mf_end != 0 &&
server.cluster->mf_can_start;
- int j;
mstime_t auth_timeout, auth_retry_time;
server.cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER;
@@ -2792,26 +2827,12 @@ void clusterHandleSlaveFailover(void) {
/* Check if we reached the quorum. */
if (server.cluster->failover_auth_count >= needed_quorum) {
- clusterNode *oldmaster = myself->slaveof;
+ /* We have the quorum, we can finally failover the master. */
redisLog(REDIS_WARNING,
"Failover election won: I'm the new master.");
- /* We have the quorum, perform all the steps to correctly promote
- * this slave to a master.
- *
- * 1) Turn this node into a master. */
- clusterSetNodeAsMaster(myself);
- replicationUnsetMaster();
- /* 2) Claim all the slots assigned to our master. */
- for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
- if (clusterNodeGetSlotBit(oldmaster,j)) {
- clusterDelSlot(j);
- clusterAddSlot(myself,j);
- }
- }
-
- /* 3) Update my configEpoch to the epoch of the election. */
+ /* Update my configEpoch to the epoch of the election. */
if (myself->configEpoch < server.cluster->failover_auth_epoch) {
myself->configEpoch = server.cluster->failover_auth_epoch;
redisLog(REDIS_WARNING,
@@ -2819,16 +2840,8 @@ void clusterHandleSlaveFailover(void) {
(unsigned long long) myself->configEpoch);
}
- /* 4) Update state and save config. */
- clusterUpdateState();
- clusterSaveConfigOrDie(1);
-
- /* 5) Pong all the other nodes so that they can update the state
- * accordingly and detect that we switched to master role. */
- clusterBroadcastPong(CLUSTER_BROADCAST_ALL);
-
- /* 6) If there was a manual failover in progress, clear the state. */
- resetManualFailover();
+ /* Take responsability for the cluster slots. */
+ clusterFailoverReplaceYourMaster();
} else {
clusterLogCantFailover(REDIS_CLUSTER_CANT_FAILOVER_WAITING_VOTES);
}