MCPcopy Create free account
hub / github.com/F-Stack/f-stack / clusterHandleSlaveMigration

Function clusterHandleSlaveMigration

app/redis-6.2.6/src/cluster.c:3332–3415  ·  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

3330 * Additional conditions for migration are examined inside the function.
3331 */
3332void clusterHandleSlaveMigration(int max_slaves) {
3333 int j, okslaves = 0;
3334 clusterNode *mymaster = myself->slaveof, *target = NULL, *candidate = NULL;
3335 dictIterator *di;
3336 dictEntry *de;
3337
3338 /* Step 1: Don't migrate if the cluster state is not ok. */
3339 if (server.cluster->state != CLUSTER_OK) return;
3340
3341 /* Step 2: Don't migrate if my master will not be left with at least
3342 * 'migration-barrier' slaves after my migration. */
3343 if (mymaster == NULL) return;
3344 for (j = 0; j < mymaster->numslaves; j++)
3345 if (!nodeFailed(mymaster->slaves[j]) &&
3346 !nodeTimedOut(mymaster->slaves[j])) okslaves++;
3347 if (okslaves <= server.cluster_migration_barrier) return;
3348
3349 /* Step 3: Identify a candidate for migration, and check if among the
3350 * masters with the greatest number of ok slaves, I'm the one with the
3351 * smallest node ID (the "candidate slave").
3352 *
3353 * Note: this means that eventually a replica migration will occur
3354 * since slaves that are reachable again always have their FAIL flag
3355 * cleared, so eventually there must be a candidate. At the same time
3356 * this does not mean that there are no race conditions possible (two
3357 * slaves migrating at the same time), but this is unlikely to
3358 * happen, and harmless when happens. */
3359 candidate = myself;
3360 di = dictGetSafeIterator(server.cluster->nodes);
3361 while((de = dictNext(di)) != NULL) {
3362 clusterNode *node = dictGetVal(de);
3363 int okslaves = 0, is_orphaned = 1;
3364
3365 /* We want to migrate only if this master is working, orphaned, and
3366 * used to have slaves or if failed over a master that had slaves
3367 * (MIGRATE_TO flag). This way we only migrate to instances that were
3368 * supposed to have replicas. */
3369 if (nodeIsSlave(node) || nodeFailed(node)) is_orphaned = 0;
3370 if (!(node->flags & CLUSTER_NODE_MIGRATE_TO)) is_orphaned = 0;
3371
3372 /* Check number of working slaves. */
3373 if (nodeIsMaster(node)) okslaves = clusterCountNonFailingSlaves(node);
3374 if (okslaves > 0) is_orphaned = 0;
3375
3376 if (is_orphaned) {
3377 if (!target && node->numslots > 0) target = node;
3378
3379 /* Track the starting time of the orphaned condition for this
3380 * master. */
3381 if (!node->orphaned_time) node->orphaned_time = mstime();
3382 } else {
3383 node->orphaned_time = 0;
3384 }
3385
3386 /* Check if I'm the slave candidate for the migration: attached
3387 * to a master with the maximum number of slaves and with the smallest
3388 * node ID. */
3389 if (okslaves == max_slaves) {

Callers 1

clusterCronFunction · 0.85

Calls 6

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

Tested by

no test coverage detected