MCPcopy Create free account
hub / github.com/Snapchat/KeyDB / clusterHandleSlaveFailover

Function clusterHandleSlaveFailover

src/cluster.cpp:3192–3361  ·  view source on GitHub ↗

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. * * The goal of this function is: * 1) To check if we are able to perform a failover, is our data updated? * 2) Try to get elected by masters. * 3) Perform the failover informing all the other nodes. */

Source from the content-addressed store, hash-verified

3190 * 3) Perform the failover informing all the other nodes.
3191 */
3192void clusterHandleSlaveFailover(void) {
3193 mstime_t data_age;
3194 mstime_t auth_age = mstime() - g_pserver->cluster->failover_auth_time;
3195 int needed_quorum = (g_pserver->cluster->size / 2) + 1;
3196 int manual_failover = g_pserver->cluster->mf_end != 0 &&
3197 g_pserver->cluster->mf_can_start;
3198 mstime_t auth_timeout, auth_retry_time;
3199
3200 g_pserver->cluster->todo_before_sleep &= ~CLUSTER_TODO_HANDLE_FAILOVER;
3201
3202 /* Compute the failover timeout (the max time we have to send votes
3203 * and wait for replies), and the failover retry time (the time to wait
3204 * before trying to get voted again).
3205 *
3206 * Timeout is MAX(NODE_TIMEOUT*2,2000) milliseconds.
3207 * Retry is two times the Timeout.
3208 */
3209 auth_timeout = g_pserver->cluster_node_timeout*2;
3210 if (auth_timeout < 2000) auth_timeout = 2000;
3211 auth_retry_time = auth_timeout*2;
3212
3213 /* Pre conditions to run the function, that must be met both in case
3214 * of an automatic or manual failover:
3215 * 1) We are a slave.
3216 * 2) Our master is flagged as FAIL, or this is a manual failover.
3217 * 3) We don't have the no failover configuration set, and this is
3218 * not a manual failover.
3219 * 4) It is serving slots. */
3220 if (nodeIsMaster(myself) ||
3221 myself->slaveof == NULL ||
3222 (!nodeFailed(myself->slaveof) && !manual_failover) ||
3223 (g_pserver->cluster_slave_no_failover && !manual_failover) ||
3224 myself->slaveof->numslots == 0)
3225 {
3226 /* There are no reasons to failover, so we set the reason why we
3227 * are returning without failing over to NONE. */
3228 g_pserver->cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;
3229 return;
3230 }
3231
3232 /* Set data_age to the number of milliseconds we are disconnected from
3233 * the master. */
3234 if (getFirstMaster()->repl_state == REPL_STATE_CONNECTED) {
3235 data_age = (mstime_t)(g_pserver->unixtime - getFirstMaster()->master->lastinteraction)
3236 * 1000;
3237 } else {
3238 data_age = (mstime_t)(g_pserver->unixtime - getFirstMaster()->repl_down_since) * 1000;
3239 }
3240
3241 /* Remove the node timeout from the data age as it is fine that we are
3242 * disconnected from our master at least for the time it was down to be
3243 * flagged as FAIL, that's the baseline. */
3244 if (data_age > g_pserver->cluster_node_timeout)
3245 data_age -= g_pserver->cluster_node_timeout;
3246
3247 /* Check if our data is recent enough according to the slave validity
3248 * factor configured by the user.
3249 *

Callers 2

clusterCronFunction · 0.85
clusterBeforeSleepFunction · 0.85

Calls 11

getFirstMasterFunction · 0.85
clusterLogCantFailoverFunction · 0.85
randomFunction · 0.85
clusterGetSlaveRankFunction · 0.85
clusterDoBeforeSleepFunction · 0.85
serverLogFunction · 0.85
clusterBroadcastPongFunction · 0.85
mstimeFunction · 0.70

Tested by

no test coverage detected