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

Function clusterHandleSlaveMigration

src/cluster.cpp:3390–3473  ·  view source on GitHub ↗

This function is responsible to decide if this replica should be migrated * to a different (orphaned) master. It is called by the clusterCron() function * only if: * * 1) We are a slave node. * 2) It was detected that there is at least one orphaned master in * the cluster. * 3) We are a slave of one of the masters with the greatest number of * slaves. * * This checks are performed

Source from the content-addressed store, hash-verified

3388 * Additional conditions for migration are examined inside the function.
3389 */
3390void clusterHandleSlaveMigration(int max_slaves) {
3391 int j, okslaves = 0;
3392 clusterNode *mymaster = myself->slaveof, *target = NULL, *candidate = NULL;
3393 dictIterator *di;
3394 dictEntry *de;
3395
3396 /* Step 1: Don't migrate if the cluster state is not ok. */
3397 if (g_pserver->cluster->state != CLUSTER_OK) return;
3398
3399 /* Step 2: Don't migrate if my master will not be left with at least
3400 * 'migration-barrier' slaves after my migration. */
3401 if (mymaster == NULL) return;
3402 for (j = 0; j < mymaster->numslaves; j++)
3403 if (!nodeFailed(mymaster->slaves[j]) &&
3404 !nodeTimedOut(mymaster->slaves[j])) okslaves++;
3405 if (okslaves <= g_pserver->cluster_migration_barrier) return;
3406
3407 /* Step 3: Identify a candidate for migration, and check if among the
3408 * masters with the greatest number of ok slaves, I'm the one with the
3409 * smallest node ID (the "candidate slave").
3410 *
3411 * Note: this means that eventually a replica migration will occur
3412 * since slaves that are reachable again always have their FAIL flag
3413 * cleared, so eventually there must be a candidate. At the same time
3414 * this does not mean that there are no race conditions possible (two
3415 * slaves migrating at the same time), but this is unlikely to
3416 * happen, and harmless when happens. */
3417 candidate = myself;
3418 di = dictGetSafeIterator(g_pserver->cluster->nodes);
3419 while((de = dictNext(di)) != NULL) {
3420 clusterNode *node = (clusterNode*)dictGetVal(de);
3421 int okslaves = 0, is_orphaned = 1;
3422
3423 /* We want to migrate only if this master is working, orphaned, and
3424 * used to have slaves or if failed over a master that had slaves
3425 * (MIGRATE_TO flag). This way we only migrate to instances that were
3426 * supposed to have replicas. */
3427 if (nodeIsSlave(node) || nodeFailed(node)) is_orphaned = 0;
3428 if (!(node->flags & CLUSTER_NODE_MIGRATE_TO)) is_orphaned = 0;
3429
3430 /* Check number of working slaves. */
3431 if (nodeIsMaster(node)) okslaves = clusterCountNonFailingSlaves(node);
3432 if (okslaves > 0) is_orphaned = 0;
3433
3434 if (is_orphaned) {
3435 if (!target && node->numslots > 0) target = node;
3436
3437 /* Track the starting time of the orphaned condition for this
3438 * master. */
3439 if (!node->orphaned_time) node->orphaned_time = mstime();
3440 } else {
3441 node->orphaned_time = 0;
3442 }
3443
3444 /* Check if I'm the slave candidate for the migration: attached
3445 * to a master with the maximum number of slaves and with the smallest
3446 * node ID. */
3447 if (okslaves == max_slaves) {

Callers 1

clusterCronFunction · 0.85

Calls 7

dictGetSafeIteratorFunction · 0.85
serverLogFunction · 0.85
clusterSetMasterFunction · 0.85
dictNextFunction · 0.70
mstimeFunction · 0.70
dictReleaseIteratorFunction · 0.70

Tested by

no test coverage detected