protected Cluster.Action pickRandomRegions(Cluster cluster, int thisServer, int otherServer) { if (thisServer < 0 || otherServer < 0) { return Cluster.NullAction; } // Decide who is most likely to need another region int thisRegionCount = cluster.getNumRegions(thisServer); int otherRegionCount = cluster.getNumRegions(otherServer); // Assign the chance based upon the above double thisChance = (thisRegionCount > otherRegionCount) ? 0 : 0.5; double otherChance = (thisRegionCount <= otherRegionCount) ? 0 : 0.5; int thisRegion = pickRandomRegion(cluster, thisServer, thisChance); int otherRegion = pickRandomRegion(cluster, otherServer, otherChance); return getAction(thisServer, thisRegion, otherServer, otherRegion); }
protected Cluster.Action getAction (int fromServer, int fromRegion, int toServer, int toRegion) { if (fromServer < 0 || toServer < 0) { return Cluster.NullAction; } if (fromRegion > 0 && toRegion > 0) { return new Cluster.SwapRegionsAction(fromServer, fromRegion, toServer, toRegion); } else if (fromRegion > 0) { return new Cluster.MoveRegionAction(fromRegion, fromServer, toServer); } else if (toRegion > 0) { return new Cluster.MoveRegionAction(toRegion, toServer, fromServer); } else { return Cluster.NullAction; } }
@Override Cluster.Action generate(Cluster cluster) { int serverIndex = pickRandomServer(cluster); if (cluster.numServers <= 1 || serverIndex == -1) { return Cluster.NullAction; } int regionIndex = selectCoHostedRegionPerGroup( cluster.primariesOfRegionsPerServer[serverIndex], cluster.regionsPerServer[serverIndex], cluster.regionIndexToPrimaryIndex); // if there are no pairs of region replicas co-hosted, default to random generator if (regionIndex == -1) { // default to randompicker return randomGenerator.generate(cluster); } int toServerIndex = pickOtherRandomServer(cluster, serverIndex); int toRegionIndex = pickRandomRegion(cluster, toServerIndex, 0.9f); return getAction (serverIndex, regionIndex, toServerIndex, toRegionIndex); }
@Override Cluster.Action generate(Cluster cluster) { int rackIndex = pickRandomRack(cluster); if (cluster.numRacks <= 1 || rackIndex == -1) { return super.generate(cluster); } int regionIndex = selectCoHostedRegionPerGroup( cluster.primariesOfRegionsPerRack[rackIndex], cluster.regionsPerRack[rackIndex], cluster.regionIndexToPrimaryIndex); // if there are no pairs of region replicas co-hosted, default to random generator if (regionIndex == -1) { // default to randompicker return randomGenerator.generate(cluster); } int serverIndex = cluster.regionIndexToServerIndex[regionIndex]; int toRackIndex = pickOtherRandomRack(cluster, rackIndex); int rand = RANDOM.nextInt(cluster.serversPerRack[toRackIndex].length); int toServerIndex = cluster.serversPerRack[toRackIndex][rand]; int toRegionIndex = pickRandomRegion(cluster, toServerIndex, 0.9f); return getAction (serverIndex, regionIndex, toServerIndex, toRegionIndex); }
/** Called once per cluster Action to give the cost function * an opportunity to update it's state. postAction() is always * called at least once before cost() is called with the cluster * that this action is performed on. */ void postAction(Action action) { switch (action.type) { case NULL: break; case ASSIGN_REGION: AssignRegionAction ar = (AssignRegionAction) action; regionMoved(ar.region, -1, ar.server); break; case MOVE_REGION: MoveRegionAction mra = (MoveRegionAction) action; regionMoved(mra.region, mra.fromServer, mra.toServer); break; case SWAP_REGIONS: SwapRegionsAction a = (SwapRegionsAction) action; regionMoved(a.fromRegion, a.fromServer, a.toServer); regionMoved(a.toRegion, a.toServer, a.fromServer); break; default: throw new RuntimeException("Uknown action:" + action.type); } }
protected Cluster.Action getAction(int fromServer, int fromRegion, int toServer, int toRegion) { if (fromServer < 0 || toServer < 0) { return Cluster.NullAction; } if (fromRegion > 0 && toRegion > 0) { return new Cluster.SwapRegionsAction(fromServer, fromRegion, toServer, toRegion); } else if (fromRegion > 0) { return new Cluster.MoveRegionAction(fromRegion, fromServer, toServer); } else if (toRegion > 0) { return new Cluster.MoveRegionAction(toRegion, toServer, fromServer); } else { return Cluster.NullAction; } }
@Override Cluster.Action generate(Cluster cluster) { if (this.masterServices == null) { int thisServer = pickRandomServer(cluster); // Pick the other server int otherServer = pickOtherRandomServer(cluster, thisServer); return pickRandomRegions(cluster, thisServer, otherServer); } // Randomly iterate through regions until you find one that is not on ideal host for (int region : getRandomIterationOrder(cluster.numRegions)) { int currentServer = cluster.regionIndexToServerIndex[region]; if (currentServer != cluster.getOrComputeRegionsToMostLocalEntities(LocalityType.SERVER)[region]) { Optional<Action> potential = tryMoveOrSwap( cluster, currentServer, region, cluster.getOrComputeRegionsToMostLocalEntities(LocalityType.SERVER)[region] ); if (potential.isPresent()) { return potential.get(); } } } return Cluster.NullAction; }
/** * Try to generate a move/swap fromRegion between fromServer and toServer such that locality is improved. * Returns empty optional if no move can be found */ private Optional<Action> tryMoveOrSwap(Cluster cluster, int fromServer, int fromRegion, int toServer) { // Try move first. We know apriori fromRegion has the highest locality on toServer if (cluster.serverHasTooFewRegions(toServer)) { return Optional.of(getAction(fromServer, fromRegion, toServer, -1)); } // Compare locality gain/loss from swapping fromRegion with regions on toServer double fromRegionLocalityDelta = getWeightedLocality(cluster, fromRegion, toServer) - getWeightedLocality(cluster, fromRegion, fromServer); for (int toRegionIndex : getRandomIterationOrder(cluster.regionsPerServer[toServer].length)) { int toRegion = cluster.regionsPerServer[toServer][toRegionIndex]; double toRegionLocalityDelta = getWeightedLocality(cluster, toRegion, fromServer) - getWeightedLocality(cluster, toRegion, toServer); // If locality would remain neutral or improve, attempt the swap if (fromRegionLocalityDelta + toRegionLocalityDelta >= 0) { return Optional.of(getAction(fromServer, fromRegion, toServer, toRegion)); } } return Optional.absent(); }
@Override Cluster.Action generate(Cluster cluster) { int serverIndex = pickRandomServer(cluster); if (cluster.numServers <= 1 || serverIndex == -1) { return Cluster.NullAction; } int regionIndex = selectCoHostedRegionPerGroup( cluster.primariesOfRegionsPerServer[serverIndex], cluster.regionsPerServer[serverIndex], cluster.regionIndexToPrimaryIndex); // if there are no pairs of region replicas co-hosted, default to random generator if (regionIndex == -1) { // default to randompicker return randomGenerator.generate(cluster); } int toServerIndex = pickOtherRandomServer(cluster, serverIndex); int toRegionIndex = pickRandomRegion(cluster, toServerIndex, 0.9f); return getAction(serverIndex, regionIndex, toServerIndex, toRegionIndex); }
@Override Cluster.Action generate(Cluster cluster) { int rackIndex = pickRandomRack(cluster); if (cluster.numRacks <= 1 || rackIndex == -1) { return super.generate(cluster); } int regionIndex = selectCoHostedRegionPerGroup( cluster.primariesOfRegionsPerRack[rackIndex], cluster.regionsPerRack[rackIndex], cluster.regionIndexToPrimaryIndex); // if there are no pairs of region replicas co-hosted, default to random generator if (regionIndex == -1) { // default to randompicker return randomGenerator.generate(cluster); } int serverIndex = cluster.regionIndexToServerIndex[regionIndex]; int toRackIndex = pickOtherRandomRack(cluster, rackIndex); int rand = RANDOM.nextInt(cluster.serversPerRack[toRackIndex].length); int toServerIndex = cluster.serversPerRack[toRackIndex][rand]; int toRegionIndex = pickRandomRegion(cluster, toServerIndex, 0.9f); return getAction(serverIndex, regionIndex, toServerIndex, toRegionIndex); }
@Override Cluster.Action generate(Cluster cluster) { cluster.sortServersByRegionCount(); int thisServer = pickMostLoadedServer(cluster, -1); int otherServer = pickLeastLoadedServer(cluster, thisServer); return pickRandomRegions(cluster, thisServer, otherServer); }
@Override Cluster.Action generate(Cluster cluster) { if (this.masterServices == null) { return Cluster.NullAction; } // Pick a random region server int thisServer = pickRandomServer(cluster); // Pick a random region on this server int thisRegion = pickRandomRegion(cluster, thisServer, 0.0f); if (thisRegion == -1) { return Cluster.NullAction; } // Pick the server with the highest locality int otherServer = pickHighestLocalityServer(cluster, thisServer, thisRegion); if (otherServer == -1) { return Cluster.NullAction; } // pick an region on the other server to potentially swap int otherRegion = this.pickRandomRegion(cluster, otherServer, 0.5f); return getAction(thisServer, thisRegion, otherServer, otherRegion); }
protected void updateCostsWithAction(Cluster cluster, Action action) { for (CostFunction c : costFunctions) { c.postAction(action); } }
@VisibleForTesting Cluster.Action nextAction(Cluster cluster) { return candidateGenerators.get(RANDOM.nextInt(candidateGenerators.size())) .generate(cluster); }
@Override Cluster.Action generate(Cluster cluster) { int thisServer = pickRandomServer(cluster); // Pick the other server int otherServer = pickOtherRandomServer(cluster, thisServer); return pickRandomRegions(cluster, thisServer, otherServer); }
abstract Cluster.Action generate(Cluster cluster);