Search in sources :

Example 1 with OptimizationForGoal

use of com.linkedin.kafka.cruisecontrol.async.progress.OptimizationForGoal in project cruise-control by linkedin.

the class GoalOptimizer method optimizations.

/**
 * Depending the existence of dead/decommissioned brokers in the given cluster:
 * (1) Re-balance: Generates proposals to update the state of the cluster to achieve a final balanced state.
 * (2) Self-healing: Generates proposals to move replicas away from decommissioned brokers.
 * Returns a map from goal names to stats. Initial stats are returned under goal name "init".
 *
 * @param clusterModel The state of the cluster over which the balancing proposal will be applied. Function execution
 *                     updates the cluster state with balancing proposals. If the cluster model is specified, the
 *                     cached proposal will be ignored.
 * @param goalsByPriority the goals ordered by priority.
 * @param operationProgress to report the job progress.
 * @return Results of optimization containing the proposals and stats.
 */
public OptimizerResult optimizations(ClusterModel clusterModel, Map<Integer, Goal> goalsByPriority, OperationProgress operationProgress) throws KafkaCruiseControlException {
    if (clusterModel == null) {
        throw new IllegalArgumentException("The cluster model cannot be null");
    }
    // Sanity check for optimizing goals.
    if (!clusterModel.isClusterAlive()) {
        throw new IllegalArgumentException("All brokers are dead in the cluster.");
    }
    LOG.trace("Cluster before optimization is {}", clusterModel);
    ClusterModel.BrokerStats brokerStatsBeforeOptimization = clusterModel.brokerStats();
    Map<TopicPartition, List<Integer>> initReplicaDistribution = clusterModel.getReplicaDistribution();
    Map<TopicPartition, Integer> initLeaderDistribution = clusterModel.getLeaderDistribution();
    boolean isSelfHealing = !clusterModel.selfHealingEligibleReplicas().isEmpty();
    // Set of balancing proposals that will be applied to the given cluster state to satisfy goals (leadership
    // transfer AFTER partition transfer.)
    Set<Goal> optimizedGoals = new HashSet<>();
    Set<Goal> violatedGoalsBeforeOptimization = new HashSet<>();
    Set<Goal> violatedGoalsAfterOptimization = new HashSet<>();
    Map<Goal, ClusterModelStats> statsByGoalPriority = new LinkedHashMap<>();
    Map<TopicPartition, List<Integer>> preOptimizedReplicaDistribution = null;
    Map<TopicPartition, Integer> preOptimizedLeaderDistribution = null;
    Set<String> excludedTopics = excludedTopics(clusterModel);
    LOG.debug("Topics excluded from partition movement: {}", excludedTopics);
    for (Map.Entry<Integer, Goal> entry : goalsByPriority.entrySet()) {
        preOptimizedReplicaDistribution = preOptimizedReplicaDistribution == null ? initReplicaDistribution : clusterModel.getReplicaDistribution();
        preOptimizedLeaderDistribution = preOptimizedLeaderDistribution == null ? initLeaderDistribution : clusterModel.getLeaderDistribution();
        Goal goal = entry.getValue();
        OptimizationForGoal step = new OptimizationForGoal(goal.name());
        operationProgress.addStep(step);
        LOG.debug("Optimizing goal {}", goal.name());
        boolean succeeded = goal.optimize(clusterModel, optimizedGoals, excludedTopics);
        optimizedGoals.add(goal);
        statsByGoalPriority.put(goal, clusterModel.getClusterStats(_balancingConstraint));
        Set<ExecutionProposal> goalProposals = AnalyzerUtils.getDiff(preOptimizedReplicaDistribution, preOptimizedLeaderDistribution, clusterModel);
        if (!goalProposals.isEmpty() || !succeeded) {
            violatedGoalsBeforeOptimization.add(goal);
        }
        if (!succeeded) {
            violatedGoalsAfterOptimization.add(goal);
        }
        logProgress(isSelfHealing, goal.name(), optimizedGoals.size(), goalProposals);
        step.done();
        LOG.debug("Broker level stats after optimization: {}", clusterModel.brokerStats());
    }
    clusterModel.sanityCheck();
    // Broker level stats in the final cluster state.
    if (LOG.isTraceEnabled()) {
        LOG.trace("Broker level stats after optimization: {}%n", clusterModel.brokerStats());
    }
    Set<ExecutionProposal> proposals = AnalyzerUtils.getDiff(initReplicaDistribution, initLeaderDistribution, clusterModel);
    return new OptimizerResult(statsByGoalPriority, violatedGoalsBeforeOptimization, violatedGoalsAfterOptimization, proposals, brokerStatsBeforeOptimization, clusterModel.brokerStats(), clusterModel.generation(), clusterModel.getClusterStats(_balancingConstraint));
}
Also used : OptimizationForGoal(com.linkedin.kafka.cruisecontrol.async.progress.OptimizationForGoal) ClusterModelStats(com.linkedin.kafka.cruisecontrol.model.ClusterModelStats) LinkedHashMap(java.util.LinkedHashMap) ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) OptimizationForGoal(com.linkedin.kafka.cruisecontrol.async.progress.OptimizationForGoal) Goal(com.linkedin.kafka.cruisecontrol.analyzer.goals.Goal) ExecutionProposal(com.linkedin.kafka.cruisecontrol.executor.ExecutionProposal) TopicPartition(org.apache.kafka.common.TopicPartition) ArrayList(java.util.ArrayList) List(java.util.List) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) HashSet(java.util.HashSet)

Aggregations

Goal (com.linkedin.kafka.cruisecontrol.analyzer.goals.Goal)1 OptimizationForGoal (com.linkedin.kafka.cruisecontrol.async.progress.OptimizationForGoal)1 ExecutionProposal (com.linkedin.kafka.cruisecontrol.executor.ExecutionProposal)1 ClusterModel (com.linkedin.kafka.cruisecontrol.model.ClusterModel)1 ClusterModelStats (com.linkedin.kafka.cruisecontrol.model.ClusterModelStats)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 Map (java.util.Map)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 TopicPartition (org.apache.kafka.common.TopicPartition)1