Search in sources :

Example 31 with ReplicaPlacementInfo

use of com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo in project cruise-control by linkedin.

the class AbstractReplicaMovementStrategy method applyStrategy.

@Override
public Map<Integer, SortedSet<ExecutionTask>> applyStrategy(Set<ExecutionTask> replicaMovementTasks, StrategyOptions strategyOptions) {
    Map<Integer, SortedSet<ExecutionTask>> tasksByBrokerId = new HashMap<>();
    for (ExecutionTask task : replicaMovementTasks) {
        ExecutionProposal proposal = task.proposal();
        // Add the task to source broker's execution plan
        SortedSet<ExecutionTask> sourceBrokerTaskSet = tasksByBrokerId.computeIfAbsent(proposal.oldLeader().brokerId(), k -> new TreeSet<>(taskComparator(strategyOptions)));
        if (!sourceBrokerTaskSet.add(task)) {
            throw new IllegalStateException("Replica movement strategy " + this.getClass().getSimpleName() + " failed to determine order of tasks.");
        }
        // Add the task to destination brokers' execution plan
        for (ReplicaPlacementInfo destinationBroker : proposal.replicasToAdd()) {
            SortedSet<ExecutionTask> destinationBrokerTaskSet = tasksByBrokerId.computeIfAbsent(destinationBroker.brokerId(), k -> new TreeSet<>(taskComparator(strategyOptions)));
            if (!destinationBrokerTaskSet.add(task)) {
                throw new IllegalStateException("Replica movement strategy " + this.getClass().getSimpleName() + " failed to determine order of tasks.");
            }
        }
    }
    return tasksByBrokerId;
}
Also used : ExecutionProposal(com.linkedin.kafka.cruisecontrol.executor.ExecutionProposal) HashMap(java.util.HashMap) ExecutionTask(com.linkedin.kafka.cruisecontrol.executor.ExecutionTask) SortedSet(java.util.SortedSet) ReplicaPlacementInfo(com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo)

Example 32 with ReplicaPlacementInfo

use of com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo in project cruise-control by linkedin.

the class GoalViolationDetector method optimizeForGoal.

protected boolean optimizeForGoal(ClusterModel clusterModel, Goal goal, GoalViolations goalViolations, Set<Integer> excludedBrokersForLeadership, Set<Integer> excludedBrokersForReplicaMove, boolean checkPartitionsWithRFGreaterThanNumRacks) throws KafkaCruiseControlException {
    if (clusterModel.topics().isEmpty()) {
        LOG.info("Skipping goal violation detection because the cluster model does not have any topic.");
        return false;
    }
    Map<TopicPartition, List<ReplicaPlacementInfo>> initReplicaDistribution = clusterModel.getReplicaDistribution();
    Map<TopicPartition, ReplicaPlacementInfo> initLeaderDistribution = clusterModel.getLeaderDistribution();
    try {
        OptimizationOptions options = _optimizationOptionsGenerator.optimizationOptionsForGoalViolationDetection(clusterModel, excludedTopics(clusterModel), excludedBrokersForLeadership, excludedBrokersForReplicaMove);
        if (checkPartitionsWithRFGreaterThanNumRacks) {
            _hasPartitionsWithRFGreaterThanNumRacks = clusterModel.maxReplicationFactor() > clusterModel.numAliveRacksAllowedReplicaMoves(options);
        }
        goal.optimize(clusterModel, Collections.emptySet(), options);
    } catch (OptimizationFailureException ofe) {
        // An OptimizationFailureException indicates (1) a hard goal violation that cannot be fixed typically due to
        // lack of physical hardware (e.g. insufficient number of racks to satisfy rack awareness, insufficient number
        // of brokers to satisfy Replica Capacity Goal, or insufficient number of resources to satisfy resource
        // capacity goals), or (2) a failure to move offline replicas away from dead brokers/disks.
        goalViolations.addViolation(goal.name(), false);
        return true;
    }
    boolean hasDiff = AnalyzerUtils.hasDiff(initReplicaDistribution, initLeaderDistribution, clusterModel);
    LOG.trace("{} generated {} proposals", goal.name(), hasDiff ? "some" : "no");
    if (hasDiff) {
        // A goal violation that can be optimized by applying the generated proposals.
        goalViolations.addViolation(goal.name(), true);
        return true;
    } else {
        // The goal is already satisfied.
        return false;
    }
}
Also used : OptimizationFailureException(com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException) OptimizationOptions(com.linkedin.kafka.cruisecontrol.analyzer.OptimizationOptions) TopicPartition(org.apache.kafka.common.TopicPartition) List(java.util.List) ReplicaPlacementInfo(com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo)

Example 33 with ReplicaPlacementInfo

use of com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo in project cruise-control by linkedin.

the class LowResourceUtilizationTest method test.

@Test
public void test() throws OptimizationFailureException {
    ClusterModel clusterModel = createSmallClusterModel();
    Map<TopicPartition, List<ReplicaPlacementInfo>> initReplicaDistribution = clusterModel.getReplicaDistribution();
    Map<TopicPartition, ReplicaPlacementInfo> initLeaderDistribution = clusterModel.getLeaderDistribution();
    // Before the optimization, goals are expected to be undecided wrt their provision status.
    assertEquals(ProvisionStatus.UNDECIDED, _resourceDistributionGoal.provisionResponse().status());
    assertTrue("Failed to optimize " + _resourceDistributionGoal.name(), _resourceDistributionGoal.optimize(clusterModel, Collections.emptySet(), new OptimizationOptions(Collections.emptySet(), Collections.emptySet(), Collections.emptySet())));
    // Since all optimizations succeed, it is guaranteed that all brokers have resource utilization under low utilization threshold.
    assertEquals(ProvisionStatus.OVER_PROVISIONED, _resourceDistributionGoal.provisionResponse().status());
    boolean hasDiff = AnalyzerUtils.hasDiff(initReplicaDistribution, initLeaderDistribution, clusterModel);
    if (_expectRebalance) {
        assertTrue(hasDiff);
    } else {
        assertFalse(hasDiff);
    }
}
Also used : ClusterModel(com.linkedin.kafka.cruisecontrol.model.ClusterModel) TopicPartition(org.apache.kafka.common.TopicPartition) ArrayList(java.util.ArrayList) List(java.util.List) ReplicaPlacementInfo(com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo) Test(org.junit.Test)

Example 34 with ReplicaPlacementInfo

use of com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo in project cruise-control by linkedin.

the class ReplicationFactorChangeTest method test.

@Test
public void test() throws Exception {
    prepareContext();
    Map<TopicPartition, List<ReplicaPlacementInfo>> initReplicaDistribution = _clusterModel.getReplicaDistribution();
    Map<TopicPartition, ReplicaPlacementInfo> initLeaderDistribution = _clusterModel.getLeaderDistribution();
    _clusterModel.createOrDeleteReplicas(Collections.singletonMap(_replicationFactor, _topics), _brokersByRack, _rackByBroker, _cluster);
    // Before the optimization, goals are expected to be undecided wrt their provision status.
    assertEquals(ProvisionStatus.UNDECIDED, _goal.provisionResponse().status());
    if (_exceptionClass == null) {
        if (_expectedToOptimize) {
            assertTrue("Replication factor change test with goal " + _goal.name() + " failed.", _goal.optimize(_clusterModel, Collections.emptySet(), _optimizationOptions));
        } else {
            assertFalse("Replication factor change test with goal " + _goal.name() + " should not succeed.", _goal.optimize(_clusterModel, Collections.emptySet(), _optimizationOptions));
        }
        // The cluster cannot be underprovisioned, because _exceptionClass was null.
        assertNotEquals(ProvisionStatus.UNDER_PROVISIONED, _goal.provisionResponse().status());
        Set<ExecutionProposal> goalProposals = AnalyzerUtils.getDiff(initReplicaDistribution, initLeaderDistribution, _clusterModel, true);
        for (ExecutionProposal proposal : goalProposals) {
            // Replication factor change should only be applied to specified topics.
            if (!_topics.contains(proposal.topic())) {
                fail("Replication factor change should not apply to topic %s." + proposal.topic());
            }
            if (proposal.newReplicas().size() != _replicationFactor) {
                fail(String.format("Topic partition %s's replication factor is not changed to %d.", proposal.topicPartition(), _replicationFactor));
            }
            // Increase replication factor should not touch the existing replicas.
            if (_replicationFactor >= proposal.oldReplicas().size() && !proposal.replicasToRemove().isEmpty()) {
                fail(String.format("Increasing topic partition %s's replication factor to %d should not move existing replicas.", proposal.topicPartition(), _replicationFactor));
            }
        }
        // Ensure all the specified topic has target replication factor.
        for (String topic : _topics) {
            for (PartitionInfo partitioninfo : _cluster.partitionsForTopic(topic)) {
                TopicPartition tp = new TopicPartition(topic, partitioninfo.partition());
                if (_clusterModel.partition(tp).replicas().size() != _replicationFactor) {
                    fail(String.format("Topic partition %s's replication factor is not changed to %d", tp, _replicationFactor));
                }
            }
        }
    } else {
        assertThrows(_exceptionClass, () -> _goal.optimize(_clusterModel, Collections.emptySet(), _optimizationOptions));
    }
}
Also used : ExecutionProposal(com.linkedin.kafka.cruisecontrol.executor.ExecutionProposal) TopicPartition(org.apache.kafka.common.TopicPartition) List(java.util.List) ArrayList(java.util.ArrayList) PartitionInfo(org.apache.kafka.common.PartitionInfo) ReplicaPlacementInfo(com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo) Test(org.junit.Test)

Example 35 with ReplicaPlacementInfo

use of com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo in project cruise-control by linkedin.

the class ExcludedBrokersForReplicaMoveTest method test.

@Test
public void test() throws Exception {
    // Before the optimization, goals are expected to be undecided wrt their provision status.
    assertEquals(ProvisionStatus.UNDECIDED, _goal.provisionResponse().status());
    if (_exceptionClass == null) {
        Map<TopicPartition, List<ReplicaPlacementInfo>> initReplicaDistribution = _clusterModel.getReplicaDistribution();
        Map<TopicPartition, ReplicaPlacementInfo> initLeaderDistribution = _clusterModel.getLeaderDistribution();
        Set<Integer> excludedBrokersForReplicaMove = _optimizationOptions.excludedBrokersForReplicaMove();
        if (_expectedToOptimize) {
            assertTrue("Failed to optimize " + _goal.name() + " with excluded brokers for replica move.", _goal.optimize(_clusterModel, Collections.emptySet(), _optimizationOptions));
        } else {
            assertFalse("Optimized " + _goal.name() + " with excluded brokers for replicaMove " + excludedBrokersForReplicaMove, _goal.optimize(_clusterModel, Collections.emptySet(), _optimizationOptions));
        }
        // The cluster cannot be underprovisioned, because _exceptionClass was null.
        assertNotEquals(ProvisionStatus.UNDER_PROVISIONED, _goal.provisionResponse().status());
        // Generated proposals cannot move replicas to the excluded brokers for replica move.
        if (!excludedBrokersForReplicaMove.isEmpty()) {
            Set<ExecutionProposal> goalProposals = AnalyzerUtils.getDiff(initReplicaDistribution, initLeaderDistribution, _clusterModel);
            assertEquals(_expectedToGenerateProposals, !goalProposals.isEmpty());
            for (ExecutionProposal proposal : goalProposals) {
                if (proposal.hasReplicaAction() && violatesExcludedBrokersForReplicaMove(excludedBrokersForReplicaMove, proposal)) {
                    fail(String.format("A replica move in %s to an excluded broker for replica move %s.", proposal, excludedBrokersForReplicaMove));
                }
            }
        }
    } else {
        _expected.expect(_exceptionClass);
        assertTrue("Failed to optimize with excluded brokers for replica move.", _goal.optimize(_clusterModel, Collections.emptySet(), _optimizationOptions));
        assertEquals(ProvisionStatus.UNDER_PROVISIONED, _goal.provisionResponse().status());
    }
}
Also used : ExecutionProposal(com.linkedin.kafka.cruisecontrol.executor.ExecutionProposal) TopicPartition(org.apache.kafka.common.TopicPartition) List(java.util.List) ArrayList(java.util.ArrayList) ReplicaPlacementInfo(com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo) Test(org.junit.Test)

Aggregations

ReplicaPlacementInfo (com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo)36 TopicPartition (org.apache.kafka.common.TopicPartition)26 Test (org.junit.Test)23 List (java.util.List)12 ArrayList (java.util.ArrayList)11 ExecutionProposal (com.linkedin.kafka.cruisecontrol.executor.ExecutionProposal)8 KafkaZkClient (kafka.zk.KafkaZkClient)8 HashMap (java.util.HashMap)6 AdminClient (org.apache.kafka.clients.admin.AdminClient)6 HashSet (java.util.HashSet)5 AlterPartitionReassignmentsResult (org.apache.kafka.clients.admin.AlterPartitionReassignmentsResult)4 Node (org.apache.kafka.common.Node)4 KafkaCruiseControlConfig (com.linkedin.kafka.cruisecontrol.config.KafkaCruiseControlConfig)3 ClusterModel (com.linkedin.kafka.cruisecontrol.model.ClusterModel)3 Properties (java.util.Properties)3 TopicDescription (org.apache.kafka.clients.admin.TopicDescription)3 Cluster (org.apache.kafka.common.Cluster)3 PartitionInfo (org.apache.kafka.common.PartitionInfo)3 MetricRegistry (com.codahale.metrics.MetricRegistry)2 Goal (com.linkedin.kafka.cruisecontrol.analyzer.goals.Goal)2