use of com.linkedin.kafka.cruisecontrol.model.ClusterModel in project cruise-control by linkedin.
the class ReplicaDistributionGoal method rebalanceByMovingReplicasOut.
private boolean rebalanceByMovingReplicasOut(Broker broker, ClusterModel clusterModel, Set<Goal> optimizedGoals, Set<String> excludedTopics) {
// Get the eligible brokers.
SortedSet<Broker> candidateBrokers = new TreeSet<>(Comparator.comparingInt((Broker b) -> b.replicas().size()).thenComparingInt(Broker::id));
candidateBrokers.addAll(_selfHealingDeadBrokersOnly ? clusterModel.healthyBrokers() : clusterModel.healthyBrokers().stream().filter(b -> b.replicas().size() < _balanceUpperLimit).collect(Collectors.toSet()));
// Get the replicas to rebalance. Replicas are sorted from smallest to largest disk usage.
List<Replica> replicasToMove = broker.sortedReplicas(Resource.DISK, true);
// Now let's move things around.
for (Replica replica : replicasToMove) {
if (shouldExclude(replica, excludedTopics)) {
continue;
}
Broker b = maybeApplyBalancingAction(clusterModel, replica, candidateBrokers, ActionType.REPLICA_MOVEMENT, optimizedGoals);
// Only check if we successfully moved something.
if (b != null) {
if (broker.replicas().size() <= (broker.isAlive() ? _balanceUpperLimit : 0)) {
return false;
}
// Remove and reinsert the broker so the order is correct.
candidateBrokers.remove(b);
if (b.replicas().size() < _balanceUpperLimit || _selfHealingDeadBrokersOnly) {
candidateBrokers.add(b);
}
}
}
// All the replicas has been moved away from the broker.
return !broker.replicas().isEmpty();
}
use of com.linkedin.kafka.cruisecontrol.model.ClusterModel in project cruise-control by linkedin.
the class ResourceDistributionGoal method rebalanceBySwappingLoadIn.
private boolean rebalanceBySwappingLoadIn(Broker broker, ClusterModel clusterModel, Set<Goal> optimizedGoals, Set<String> excludedTopics) {
if (!broker.isAlive() || broker.replicas().isEmpty()) {
// Source broker is dead or has no replicas to swap.
return true;
}
// Get the replicas to rebalance.
SortedSet<Replica> sourceReplicas = new TreeSet<>(Comparator.comparingDouble((Replica r) -> r.load().expectedUtilizationFor(resource())).thenComparing(r -> r.topicPartition().toString()));
sourceReplicas.addAll(broker.replicas());
// Sort the replicas initially to avoid sorting it every time.
PriorityQueue<CandidateBroker> candidateBrokerPQ = new PriorityQueue<>();
for (Broker candidate : clusterModel.healthyBrokersOverThreshold(resource(), _balanceLowerThreshold)) {
// Get candidate replicas on candidate broker to try swapping with -- sorted in the order of trial (descending load).
double minSourceReplicaLoad = sourceReplicas.first().load().expectedUtilizationFor(resource());
SortedSet<Replica> replicasToSwapWith = sortedCandidateReplicas(candidate, excludedTopics, minSourceReplicaLoad, false);
CandidateBroker candidateBroker = new CandidateBroker(candidate, replicasToSwapWith, false);
candidateBrokerPQ.add(candidateBroker);
}
while (!candidateBrokerPQ.isEmpty()) {
CandidateBroker cb = candidateBrokerPQ.poll();
SortedSet<Replica> candidateReplicasToSwapWith = cb.replicas();
Replica swappedInReplica = null;
Replica swappedOutReplica = null;
for (Replica sourceReplica : sourceReplicas) {
if (shouldExclude(sourceReplica, excludedTopics)) {
continue;
}
// It does not make sense to swap replicas without utilization from a live broker.
double sourceReplicaUtilization = sourceReplica.load().expectedUtilizationFor(resource());
if (sourceReplicaUtilization == 0.0) {
break;
}
// Try swapping the source with the candidate replicas. Get the swapped in replica if successful, null otherwise.
Replica swappedIn = maybeApplySwapAction(clusterModel, sourceReplica, candidateReplicasToSwapWith, optimizedGoals);
if (swappedIn != null) {
if (isLoadAboveBalanceLowerLimit(broker)) {
// Successfully balanced this broker by swapping in.
return false;
}
// Add swapped in/out replica for updating the list of replicas in source broker.
swappedInReplica = swappedIn;
swappedOutReplica = sourceReplica;
break;
}
}
swapUpdate(swappedInReplica, swappedOutReplica, sourceReplicas, candidateReplicasToSwapWith, candidateBrokerPQ, cb);
}
return true;
}
use of com.linkedin.kafka.cruisecontrol.model.ClusterModel in project cruise-control by linkedin.
the class ResourceDistributionGoal method rebalanceBySwappingLoadOut.
private boolean rebalanceBySwappingLoadOut(Broker broker, ClusterModel clusterModel, Set<Goal> optimizedGoals, Set<String> excludedTopics) {
if (!broker.isAlive()) {
return true;
}
// Get the replicas to rebalance.
SortedSet<Replica> sourceReplicas = new TreeSet<>((r1, r2) -> {
int result = Double.compare(r2.load().expectedUtilizationFor(resource()), r1.load().expectedUtilizationFor(resource()));
return result == 0 ? r1.topicPartition().toString().compareTo(r2.topicPartition().toString()) : result;
});
sourceReplicas.addAll(resource() == Resource.NW_OUT ? broker.leaderReplicas() : broker.replicas());
// Sort the replicas initially to avoid sorting it every time.
PriorityQueue<CandidateBroker> candidateBrokerPQ = new PriorityQueue<>();
for (Broker candidate : clusterModel.healthyBrokersUnderThreshold(resource(), _balanceUpperThreshold).stream().filter(b -> !b.replicas().isEmpty()).collect(Collectors.toSet())) {
// Get candidate replicas on candidate broker to try swapping with -- sorted in the order of trial (ascending load).
double maxSourceReplicaLoad = sourceReplicas.first().load().expectedUtilizationFor(resource());
SortedSet<Replica> replicasToSwapWith = sortedCandidateReplicas(candidate, excludedTopics, maxSourceReplicaLoad, true);
CandidateBroker candidateBroker = new CandidateBroker(candidate, replicasToSwapWith, true);
candidateBrokerPQ.add(candidateBroker);
}
while (!candidateBrokerPQ.isEmpty()) {
CandidateBroker cb = candidateBrokerPQ.poll();
SortedSet<Replica> candidateReplicasToSwapWith = cb.replicas();
Replica swappedInReplica = null;
Replica swappedOutReplica = null;
for (Replica sourceReplica : sourceReplicas) {
if (shouldExclude(sourceReplica, excludedTopics)) {
continue;
}
// Try swapping the source with the candidate replicas. Get the swapped in replica if successful, null otherwise.
Replica swappedIn = maybeApplySwapAction(clusterModel, sourceReplica, candidateReplicasToSwapWith, optimizedGoals);
if (swappedIn != null) {
if (isLoadUnderBalanceUpperLimit(broker)) {
// Successfully balanced this broker by swapping in.
return false;
}
// Add swapped in/out replica for updating the list of replicas in source broker.
swappedInReplica = swappedIn;
swappedOutReplica = sourceReplica;
break;
}
}
swapUpdate(swappedInReplica, swappedOutReplica, sourceReplicas, candidateReplicasToSwapWith, candidateBrokerPQ, cb);
}
return true;
}
use of com.linkedin.kafka.cruisecontrol.model.ClusterModel in project cruise-control by linkedin.
the class KafkaAssignerDiskUsageDistributionGoal method optimize.
@Override
public boolean optimize(ClusterModel clusterModel, Set<Goal> optimizedGoals, Set<String> excludedTopics) {
double meanDiskUsage = clusterModel.load().expectedUtilizationFor(DISK) / clusterModel.capacityFor(DISK);
double upperThreshold = meanDiskUsage * (1 + balancePercentageWithMargin());
double lowerThreshold = meanDiskUsage * Math.max(0, (1 - balancePercentageWithMargin()));
Comparator<Broker> comparator = (b1, b2) -> {
int result = Double.compare(diskUsage(b2), diskUsage(b1));
return result == 0 ? Integer.compare(b1.id(), b2.id()) : result;
};
boolean improved;
int numIterations = 0;
do {
List<Broker> brokers = new ArrayList<>();
brokers.addAll(clusterModel.healthyBrokers());
brokers.sort(comparator);
improved = false;
LOG.debug("Starting iteration {}", numIterations);
for (Broker broker : brokers) {
if (checkAndOptimize(broker, clusterModel, meanDiskUsage, lowerThreshold, upperThreshold, excludedTopics)) {
improved = true;
}
}
numIterations++;
} while (improved);
boolean succeeded = isOptimized(clusterModel, upperThreshold, lowerThreshold);
LOG.debug("Finished optimization in {} iterations.", numIterations);
return succeeded;
}
use of com.linkedin.kafka.cruisecontrol.model.ClusterModel in project cruise-control by linkedin.
the class LeaderBytesInDistributionGoal method rebalanceForBroker.
@Override
protected void rebalanceForBroker(Broker broker, ClusterModel clusterModel, Set<Goal> optimizedGoals, Set<String> excludedTopics) {
double balanceThreshold = balanceThreshold(clusterModel, broker.id());
if (broker.leadershipLoadForNwResources().expectedUtilizationFor(Resource.NW_IN) < balanceThreshold) {
return;
}
List<Replica> leaderReplicasSortedByBytesIn = broker.replicas().stream().filter(Replica::isLeader).filter(r -> !shouldExclude(r, excludedTopics)).sorted((a, b) -> Double.compare(b.load().expectedUtilizationFor(Resource.NW_IN), a.load().expectedUtilizationFor(Resource.NW_IN))).collect(Collectors.toList());
boolean overThreshold = true;
Iterator<Replica> leaderReplicaIt = leaderReplicasSortedByBytesIn.iterator();
while (overThreshold && leaderReplicaIt.hasNext()) {
Replica leaderReplica = leaderReplicaIt.next();
List<Replica> followers = clusterModel.partition(leaderReplica.topicPartition()).followers();
List<Broker> eligibleBrokers = followers.stream().map(Replica::broker).sorted(Comparator.comparingDouble(a -> a.leadershipLoadForNwResources().expectedUtilizationFor(Resource.NW_IN))).collect(Collectors.toList());
maybeApplyBalancingAction(clusterModel, leaderReplica, eligibleBrokers, ActionType.LEADERSHIP_MOVEMENT, optimizedGoals);
overThreshold = broker.leadershipLoadForNwResources().expectedUtilizationFor(Resource.NW_IN) > balanceThreshold;
}
if (overThreshold) {
_overLimitBrokerIds.add(broker.id());
}
}
Aggregations