Search in sources :

Example 1 with ClusterModel

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();
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) SortedSet(java.util.SortedSet) REPLICA_REJECT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.REPLICA_REJECT) PriorityQueue(java.util.PriorityQueue) ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) LoggerFactory(org.slf4j.LoggerFactory) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) OptimizationFailureException(com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) Logger(org.slf4j.Logger) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint) Set(java.util.Set) AnalyzerUtils(com.linkedin.kafka.cruisecontrol.analyzer.AnalyzerUtils) ACCEPT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.ACCEPT) ActionType(com.linkedin.kafka.cruisecontrol.analyzer.ActionType) Collectors(java.util.stream.Collectors) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) List(java.util.List) Statistic(com.linkedin.kafka.cruisecontrol.common.Statistic) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) Resource(com.linkedin.kafka.cruisecontrol.common.Resource) ClusterModelStats(com.linkedin.kafka.cruisecontrol.model.ClusterModelStats) ADD(com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaDistributionGoal.ChangeType.ADD) REMOVE(com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaDistributionGoal.ChangeType.REMOVE) Comparator(java.util.Comparator) Collections(java.util.Collections) ModelCompletenessRequirements(com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) TreeSet(java.util.TreeSet) Replica(com.linkedin.kafka.cruisecontrol.model.Replica)

Example 2 with ClusterModel

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;
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) SortedSet(java.util.SortedSet) REPLICA_REJECT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.REPLICA_REJECT) PriorityQueue(java.util.PriorityQueue) ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) LoggerFactory(org.slf4j.LoggerFactory) LEADERSHIP_MOVEMENT(com.linkedin.kafka.cruisecontrol.analyzer.ActionType.LEADERSHIP_MOVEMENT) Function(java.util.function.Function) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) REPLICA_SWAP(com.linkedin.kafka.cruisecontrol.analyzer.ActionType.REPLICA_SWAP) OptimizationFailureException(com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException) Load(com.linkedin.kafka.cruisecontrol.model.Load) REMOVE(com.linkedin.kafka.cruisecontrol.analyzer.goals.ResourceDistributionGoal.ChangeType.REMOVE) ADD(com.linkedin.kafka.cruisecontrol.analyzer.goals.ResourceDistributionGoal.ChangeType.ADD) REPLICA_MOVEMENT(com.linkedin.kafka.cruisecontrol.analyzer.ActionType.REPLICA_MOVEMENT) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint) Set(java.util.Set) ACCEPT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.ACCEPT) ActionType(com.linkedin.kafka.cruisecontrol.analyzer.ActionType) Collectors(java.util.stream.Collectors) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) List(java.util.List) Statistic(com.linkedin.kafka.cruisecontrol.common.Statistic) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) Resource(com.linkedin.kafka.cruisecontrol.common.Resource) ClusterModelStats(com.linkedin.kafka.cruisecontrol.model.ClusterModelStats) Comparator(java.util.Comparator) Collections(java.util.Collections) ModelCompletenessRequirements(com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) TreeSet(java.util.TreeSet) PriorityQueue(java.util.PriorityQueue) Replica(com.linkedin.kafka.cruisecontrol.model.Replica)

Example 3 with ClusterModel

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;
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) SortedSet(java.util.SortedSet) REPLICA_REJECT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.REPLICA_REJECT) PriorityQueue(java.util.PriorityQueue) ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) LoggerFactory(org.slf4j.LoggerFactory) LEADERSHIP_MOVEMENT(com.linkedin.kafka.cruisecontrol.analyzer.ActionType.LEADERSHIP_MOVEMENT) Function(java.util.function.Function) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) REPLICA_SWAP(com.linkedin.kafka.cruisecontrol.analyzer.ActionType.REPLICA_SWAP) OptimizationFailureException(com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException) Load(com.linkedin.kafka.cruisecontrol.model.Load) REMOVE(com.linkedin.kafka.cruisecontrol.analyzer.goals.ResourceDistributionGoal.ChangeType.REMOVE) ADD(com.linkedin.kafka.cruisecontrol.analyzer.goals.ResourceDistributionGoal.ChangeType.ADD) REPLICA_MOVEMENT(com.linkedin.kafka.cruisecontrol.analyzer.ActionType.REPLICA_MOVEMENT) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint) Set(java.util.Set) ACCEPT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.ACCEPT) ActionType(com.linkedin.kafka.cruisecontrol.analyzer.ActionType) Collectors(java.util.stream.Collectors) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) List(java.util.List) Statistic(com.linkedin.kafka.cruisecontrol.common.Statistic) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) Resource(com.linkedin.kafka.cruisecontrol.common.Resource) ClusterModelStats(com.linkedin.kafka.cruisecontrol.model.ClusterModelStats) Comparator(java.util.Comparator) Collections(java.util.Collections) ModelCompletenessRequirements(com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) TreeSet(java.util.TreeSet) PriorityQueue(java.util.PriorityQueue) Replica(com.linkedin.kafka.cruisecontrol.model.Replica) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint)

Example 4 with ClusterModel

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;
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) TopicPartition(org.apache.kafka.common.TopicPartition) Logger(org.slf4j.Logger) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint) Collection(java.util.Collection) ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) LoggerFactory(org.slf4j.LoggerFactory) Set(java.util.Set) DISK(com.linkedin.kafka.cruisecontrol.common.Resource.DISK) ArrayList(java.util.ArrayList) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) HashSet(java.util.HashSet) KafkaCruiseControlConfig(com.linkedin.kafka.cruisecontrol.config.KafkaCruiseControlConfig) Goal(com.linkedin.kafka.cruisecontrol.analyzer.goals.Goal) List(java.util.List) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) Resource(com.linkedin.kafka.cruisecontrol.common.Resource) ClusterModelStats(com.linkedin.kafka.cruisecontrol.model.ClusterModelStats) Map(java.util.Map) StringJoiner(java.util.StringJoiner) Comparator(java.util.Comparator) Collections(java.util.Collections) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) ModelCompletenessRequirements(com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) ArrayList(java.util.ArrayList) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint)

Example 5 with ClusterModel

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());
    }
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) Arrays(java.util.Arrays) SortedSet(java.util.SortedSet) REPLICA_REJECT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.REPLICA_REJECT) ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) LoggerFactory(org.slf4j.LoggerFactory) HashSet(java.util.HashSet) Mean(org.apache.commons.math3.stat.descriptive.moment.Mean) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) BalancingConstraint(com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint) Collection(java.util.Collection) Set(java.util.Set) AnalyzerUtils(com.linkedin.kafka.cruisecontrol.analyzer.AnalyzerUtils) ACCEPT(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance.ACCEPT) ActionType(com.linkedin.kafka.cruisecontrol.analyzer.ActionType) RawAndDerivedResource(com.linkedin.kafka.cruisecontrol.model.RawAndDerivedResource) Collectors(java.util.stream.Collectors) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) List(java.util.List) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) Resource(com.linkedin.kafka.cruisecontrol.common.Resource) ClusterModelStats(com.linkedin.kafka.cruisecontrol.model.ClusterModelStats) Variance(org.apache.commons.math3.stat.descriptive.moment.Variance) Comparator(java.util.Comparator) ModelCompletenessRequirements(com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements) Broker(com.linkedin.kafka.cruisecontrol.model.Broker) Replica(com.linkedin.kafka.cruisecontrol.model.Replica)

Aggregations

ClusterModel (com.linkedin.kafka.cruisecontrol.model.ClusterModel)38 TopicPartition (org.apache.kafka.common.TopicPartition)12 ModelCompletenessRequirements (com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements)11 Test (org.junit.Test)11 BalancingConstraint (com.linkedin.kafka.cruisecontrol.analyzer.BalancingConstraint)10 Replica (com.linkedin.kafka.cruisecontrol.model.Replica)10 Broker (com.linkedin.kafka.cruisecontrol.model.Broker)9 ClusterModelStats (com.linkedin.kafka.cruisecontrol.model.ClusterModelStats)9 List (java.util.List)9 HashSet (java.util.HashSet)8 Goal (com.linkedin.kafka.cruisecontrol.analyzer.goals.Goal)7 Resource (com.linkedin.kafka.cruisecontrol.common.Resource)7 Set (java.util.Set)7 Logger (org.slf4j.Logger)7 LoggerFactory (org.slf4j.LoggerFactory)7 ActionAcceptance (com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance)6 BalancingAction (com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction)6 OperationProgress (com.linkedin.kafka.cruisecontrol.async.progress.OperationProgress)6 ArrayList (java.util.ArrayList)6 Comparator (java.util.Comparator)6