Search in sources :

Example 1 with BalancingAction

use of com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction in project cruise-control by linkedin.

the class ReplicaDistributionTarget method moveReplicaToEligibleBroker.

/**
 * Move given replica to an eligible broker.
 *
 * @param clusterModel   The state of the cluster.
 * @param replicaToMove  Replica to move away from its current broker.
 * @param optimizedGoals Goals that have already been optimized. The function ensures that their requirements won't
 *                       be violated.
 * @return True if replica move succeeds, false otherwise.
 */
private boolean moveReplicaToEligibleBroker(ClusterModel clusterModel, Replica replicaToMove, Set<Goal> optimizedGoals) {
    boolean isMoveSuccessful = false;
    // Get eligible brokers to receive this replica.
    for (int brokerId : replicaToMove.broker().isAlive() ? sortedCandidateBrokerIds() : clusterModel.healthyBrokers().stream().map(Broker::id).collect(Collectors.toList())) {
        // filter out the broker that is not eligible.
        if (!isEligibleForReplica(clusterModel, replicaToMove, brokerId)) {
            continue;
        }
        // Check if movement is acceptable by this and optimized goals. Movement is acceptable by (1) this goal
        // if the eligible destination broker does not contain a replica in the same partition set, (2) optimized
        // goals if for each optimized goal accepts the replica movement action.
        BalancingAction optimizedGoalProposal = new BalancingAction(replicaToMove.topicPartition(), replicaToMove.broker().id(), brokerId, ActionType.REPLICA_MOVEMENT);
        boolean canMove = (clusterModel.broker(brokerId).replica(replicaToMove.topicPartition()) == null) && AnalyzerUtils.isProposalAcceptableForOptimizedGoals(optimizedGoals, optimizedGoalProposal, clusterModel) == ACCEPT;
        if (canMove) {
            clusterModel.relocateReplica(replicaToMove.topicPartition(), replicaToMove.broker().id(), brokerId);
            isMoveSuccessful = true;
            // Consume an eligible broker id.
            Integer requiredNumReplicas = _requiredNumReplicasByBrokerId.get(brokerId);
            if (requiredNumReplicas != null) {
                if (requiredNumReplicas == 1) {
                    _requiredNumReplicasByBrokerId.remove(brokerId);
                } else {
                    requiredNumReplicas--;
                    _requiredNumReplicasByBrokerId.put(brokerId, requiredNumReplicas);
                }
            } else {
                _secondaryEligibleBrokerIds.remove(brokerId);
            }
            break;
        }
    }
    return isMoveSuccessful;
}
Also used : Broker(com.linkedin.kafka.cruisecontrol.model.Broker) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction)

Example 2 with BalancingAction

use of com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction in project cruise-control by linkedin.

the class AbstractGoal method maybeApplySwapAction.

/**
 * Attempt to swap the given source replica with a replica from the candidate replicas to swap with. The function
 * returns the swapped in replica if succeeded, null otherwise.
 * All the replicas in the given candidateReplicasToSwapWith must be from the same broker.
 *
 * @param clusterModel The state of the cluster.
 * @param sourceReplica Replica to be swapped with.
 * @param candidateReplicasToSwapWith Candidate replicas from the same destination broker to swap in the order of
 *                                    attempts to swap.
 * @param optimizedGoals Optimized goals.
 * @return True the swapped in replica if succeeded, null otherwise.
 */
Replica maybeApplySwapAction(ClusterModel clusterModel, Replica sourceReplica, SortedSet<Replica> candidateReplicasToSwapWith, Set<Goal> optimizedGoals) {
    SortedSet<Replica> eligibleReplicas = getEligibleReplicasForSwap(clusterModel, sourceReplica, candidateReplicasToSwapWith);
    if (eligibleReplicas.isEmpty()) {
        return null;
    }
    Broker destinationBroker = eligibleReplicas.first().broker();
    for (Replica destinationReplica : eligibleReplicas) {
        BalancingAction swapProposal = new BalancingAction(sourceReplica.topicPartition(), sourceReplica.broker().id(), destinationBroker.id(), ActionType.REPLICA_SWAP, destinationReplica.topicPartition());
        // 3. The movement is acceptable by the previously optimized goals.
        if (!legitMove(sourceReplica, destinationBroker, ActionType.REPLICA_MOVEMENT)) {
            LOG.trace("Swap from source to destination is not legit for {}.", swapProposal);
            return null;
        }
        if (!legitMove(destinationReplica, sourceReplica.broker(), ActionType.REPLICA_MOVEMENT)) {
            LOG.trace("Swap from destination to source is not legit for {}.", swapProposal);
            continue;
        }
        // The current goal is expected to know whether a swap is doable between given brokers.
        if (!selfSatisfied(clusterModel, swapProposal)) {
            // Unable to satisfy proposal for this eligible replica and the remaining eligible replicas in the list.
            LOG.trace("Unable to self-satisfy swap proposal {}.", swapProposal);
            return null;
        }
        ActionAcceptance acceptance = AnalyzerUtils.isProposalAcceptableForOptimizedGoals(optimizedGoals, swapProposal, clusterModel);
        LOG.trace("Trying to apply legit and self-satisfied swap {}, actionAcceptance = {}.", swapProposal, acceptance);
        if (acceptance == ACCEPT) {
            Broker sourceBroker = sourceReplica.broker();
            clusterModel.relocateReplica(sourceReplica.topicPartition(), sourceBroker.id(), destinationBroker.id());
            clusterModel.relocateReplica(destinationReplica.topicPartition(), destinationBroker.id(), sourceBroker.id());
            return destinationReplica;
        } else if (acceptance == BROKER_REJECT) {
            // Unable to swap the given source replica with any replicas in the destination broker.
            return null;
        }
    }
    return null;
}
Also used : Broker(com.linkedin.kafka.cruisecontrol.model.Broker) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) Replica(com.linkedin.kafka.cruisecontrol.model.Replica)

Example 3 with BalancingAction

use of com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction in project cruise-control by linkedin.

the class AbstractGoal method maybeApplyBalancingAction.

/**
 * Attempt to apply the given balancing action to the given replica in the given cluster. The application
 * considers the candidate brokers as the potential destination brokers for replica movement or the location of
 * followers for leadership transfer. If the movement attempt succeeds, the function returns the broker id of the
 * destination, otherwise the function returns null.
 *
 * @param clusterModel    The state of the cluster.
 * @param replica         Replica to be applied the given balancing action.
 * @param candidateBrokers Candidate brokers as the potential destination brokers for replica movement or the location
 *                        of followers for leadership transfer.
 * @param action          Balancing action.
 * @param optimizedGoals  Optimized goals.
 * @return Broker id of the destination if the movement attempt succeeds, null otherwise.
 */
protected Broker maybeApplyBalancingAction(ClusterModel clusterModel, Replica replica, Collection<Broker> candidateBrokers, ActionType action, Set<Goal> optimizedGoals) {
    // In self healing mode, allow a move only from dead to alive brokers.
    if (!clusterModel.deadBrokers().isEmpty() && replica.originalBroker().isAlive()) {
        // return null;
        LOG.trace("Applying {} to a replica in a healthy broker in self-healing mode.", action);
    }
    Collection<Broker> eligibleBrokers = getEligibleBrokers(clusterModel, replica, candidateBrokers);
    for (Broker broker : eligibleBrokers) {
        BalancingAction proposal = new BalancingAction(replica.topicPartition(), replica.broker().id(), broker.id(), action);
        if (!legitMove(replica, broker, action)) {
            LOG.trace("Replica move is not legit for {}.", proposal);
            continue;
        }
        if (!selfSatisfied(clusterModel, proposal)) {
            LOG.trace("Unable to self-satisfy proposal {}.", proposal);
            continue;
        }
        ActionAcceptance acceptance = AnalyzerUtils.isProposalAcceptableForOptimizedGoals(optimizedGoals, proposal, clusterModel);
        LOG.trace("Trying to apply legit and self-satisfied action {}, actionAcceptance = {}", proposal, acceptance);
        if (acceptance == ACCEPT) {
            if (action == ActionType.LEADERSHIP_MOVEMENT) {
                clusterModel.relocateLeadership(replica.topicPartition(), replica.broker().id(), broker.id());
            } else if (action == ActionType.REPLICA_MOVEMENT) {
                clusterModel.relocateReplica(replica.topicPartition(), replica.broker().id(), broker.id());
            }
            return broker;
        }
    }
    return null;
}
Also used : Broker(com.linkedin.kafka.cruisecontrol.model.Broker) BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance)

Aggregations

BalancingAction (com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction)3 Broker (com.linkedin.kafka.cruisecontrol.model.Broker)3 ActionAcceptance (com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance)2 Replica (com.linkedin.kafka.cruisecontrol.model.Replica)1