Search in sources :

Example 1 with Disk

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

the class AbstractGoal method maybeMoveReplicaBetweenDisks.

/**
 * Attempt to move replica between disks of the same broker. The application considers the candidate disks as the potential
 * destination disk for replica movement. If the movement attempt succeeds, the function returns the destination disk,
 * otherwise the function returns null.
 *
 * @param clusterModel    The state of the cluster.
 * @param replica         Replica to be moved.
 * @param candidateDisks  Candidate disks as the potential destination for replica movement.
 * @param optimizedGoals  Optimized goals.
 * @return The destination disk if the movement attempt succeeds, null otherwise.
 */
protected Disk maybeMoveReplicaBetweenDisks(ClusterModel clusterModel, Replica replica, Collection<Disk> candidateDisks, Set<Goal> optimizedGoals) {
    for (Disk disk : candidateDisks) {
        BalancingAction proposal = new BalancingAction(replica.topicPartition(), replica.disk(), disk, ActionType.INTRA_BROKER_REPLICA_MOVEMENT);
        if (!legitMoveBetweenDisks(replica, disk, ActionType.INTRA_BROKER_REPLICA_MOVEMENT)) {
            LOG.trace("Replica move to disk 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) {
            clusterModel.relocateReplica(replica.topicPartition(), replica.broker().id(), disk.logDir());
            return disk;
        }
    }
    return null;
}
Also used : BalancingAction(com.linkedin.kafka.cruisecontrol.analyzer.BalancingAction) ActionAcceptance(com.linkedin.kafka.cruisecontrol.analyzer.ActionAcceptance) Disk(com.linkedin.kafka.cruisecontrol.model.Disk)

Example 2 with Disk

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

the class GoalUtils method averageDiskUtilizationPercentage.

/**
 * Get the latest average utilization percentage of all the alive disks on the broker.
 *
 * @param broker Broker for which the average disk utilization percentage has been queried.
 * @return Latest average utilization percentage of all the alive disks on the broker.
 */
public static double averageDiskUtilizationPercentage(Broker broker) {
    double totalAliveDiskCapacity = 0;
    double totalAliveDiskUtilization = 0;
    for (Disk disk : broker.disks()) {
        if (disk.isAlive()) {
            totalAliveDiskCapacity += disk.capacity();
            totalAliveDiskUtilization += disk.utilization();
        }
    }
    return totalAliveDiskCapacity > 0 ? totalAliveDiskUtilization / totalAliveDiskCapacity : DEAD_BROKER_UTILIZATION;
}
Also used : Disk(com.linkedin.kafka.cruisecontrol.model.Disk)

Example 3 with Disk

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

the class IntraBrokerDiskCapacityGoal method selfSatisfied.

@Override
protected boolean selfSatisfied(ClusterModel clusterModel, BalancingAction action) {
    Replica sourceReplica = clusterModel.broker(action.sourceBrokerId()).replica(action.topicPartition());
    Disk destinationDisk = clusterModel.broker(action.destinationBrokerId()).disk(action.destinationBrokerLogdir());
    return sourceReplica.load().expectedUtilizationFor(RESOURCE) > 0 && isMovementAcceptableForCapacity(sourceReplica, destinationDisk);
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) Disk(com.linkedin.kafka.cruisecontrol.model.Disk)

Example 4 with Disk

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

the class IntraBrokerDiskCapacityGoal method actionAcceptance.

/**
 * Check whether the given action is acceptable by this goal. An action is acceptable by a goal if it satisfies
 * requirements of the goal. For this goal:
 * ## Leadership Movement: always accept.
 * ## Replica Movement/Swap: accept if action will not make disk load exceed disk capacity limit.
 *
 * @param action Action to be checked for acceptance.
 * @param clusterModel The state of the cluster.
 * @return {@link ActionAcceptance#ACCEPT} if the action is acceptable by this goal,
 *         {@link ActionAcceptance#REPLICA_REJECT} otherwise.
 */
@Override
public ActionAcceptance actionAcceptance(BalancingAction action, ClusterModel clusterModel) {
    // Currently disk-granularity goals do not work with broker-granularity goals.
    if (action.sourceBrokerLogdir() == null || action.destinationBrokerLogdir() == null) {
        throw new IllegalArgumentException(this.getClass().getSimpleName() + " does not support balancing action not " + "specifying logdir.");
    }
    Replica sourceReplica = clusterModel.broker(action.sourceBrokerId()).replica(action.topicPartition());
    Disk destinationDisk = clusterModel.broker(action.destinationBrokerId()).disk(action.destinationBrokerLogdir());
    switch(action.balancingAction()) {
        case INTRA_BROKER_REPLICA_SWAP:
            Replica destinationReplica = clusterModel.broker(action.destinationBrokerId()).replica(action.destinationTopicPartition());
            return isSwapAcceptableForCapacity(sourceReplica, destinationReplica) ? ACCEPT : REPLICA_REJECT;
        case INTRA_BROKER_REPLICA_MOVEMENT:
            return isMovementAcceptableForCapacity(sourceReplica, destinationDisk) ? ACCEPT : REPLICA_REJECT;
        case LEADERSHIP_MOVEMENT:
            return ACCEPT;
        default:
            throw new IllegalArgumentException("Unsupported balancing action " + action.balancingAction() + " is provided.");
    }
}
Also used : Replica(com.linkedin.kafka.cruisecontrol.model.Replica) Disk(com.linkedin.kafka.cruisecontrol.model.Disk)

Example 5 with Disk

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

the class IntraBrokerDiskCapacityGoal method rebalanceForBroker.

/**
 * Perform optimization via replica movement cross disks on broker to ensure balance: The load on each alive disk
 * is under the disk's the capacity limit.
 * Note the optimization from this goal cannot be applied to offline replicas because Kafka does not support moving
 * replicas on bad disks to good disks within the same broker.
 *
 * @param broker         Broker to be balanced.
 * @param clusterModel   The state of the cluster.
 * @param optimizedGoals Optimized goals.
 * @param optimizationOptions Options to take into account during optimization.
 */
@Override
protected void rebalanceForBroker(Broker broker, ClusterModel clusterModel, Set<Goal> optimizedGoals, OptimizationOptions optimizationOptions) {
    LOG.debug("balancing broker {}, optimized goals = {}.", broker, optimizedGoals);
    // Get alive disk over capacity limit.
    List<Disk> disksOverUtilized = broker.disks().stream().filter(Disk::isAlive).filter(this::isUtilizationOverLimit).collect(Collectors.toList());
    if (disksOverUtilized.isEmpty()) {
        return;
    }
    List<Disk> candidateDisks = new ArrayList<>(broker.disks());
    candidateDisks.removeAll(disksOverUtilized);
    candidateDisks.sort(new Comparator<Disk>() {

        @Override
        public int compare(Disk disk1, Disk disk2) {
            double allowanceForDisk1 = disk1.capacity() * _balancingConstraint.capacityThreshold(RESOURCE) - disk1.utilization();
            double allowanceForDisk2 = disk2.capacity() * _balancingConstraint.capacityThreshold(RESOURCE) - disk2.utilization();
            return ((Double) (allowanceForDisk2 - allowanceForDisk1)).intValue();
        }
    });
    for (Disk disk : disksOverUtilized) {
        for (Replica replica : disk.trackedSortedReplicas(replicaSortName(this, true, false)).sortedReplicas(true)) {
            Disk d = maybeMoveReplicaBetweenDisks(clusterModel, replica, candidateDisks, optimizedGoals);
            if (d == null) {
                LOG.debug("Failed to move replica {} to any disk {} in broker {}", replica, candidateDisks, replica.broker());
            }
            if (!isUtilizationOverLimit(disk)) {
                break;
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Disk(com.linkedin.kafka.cruisecontrol.model.Disk) Replica(com.linkedin.kafka.cruisecontrol.model.Replica)

Aggregations

Disk (com.linkedin.kafka.cruisecontrol.model.Disk)16 Broker (com.linkedin.kafka.cruisecontrol.model.Broker)10 Replica (com.linkedin.kafka.cruisecontrol.model.Replica)10 ArrayList (java.util.ArrayList)4 PriorityQueue (java.util.PriorityQueue)4 HashSet (java.util.HashSet)3 TopicPartition (org.apache.kafka.common.TopicPartition)3 AggregatedMetricValues (com.linkedin.cruisecontrol.monitor.sampling.aggregator.AggregatedMetricValues)2 MetricValues (com.linkedin.cruisecontrol.monitor.sampling.aggregator.MetricValues)2 PreferredLeaderElectionGoal (com.linkedin.kafka.cruisecontrol.analyzer.goals.PreferredLeaderElectionGoal)2 Resource (com.linkedin.kafka.cruisecontrol.common.Resource)2 TestConstants (com.linkedin.kafka.cruisecontrol.common.TestConstants)2 LOGDIR0 (com.linkedin.kafka.cruisecontrol.common.TestConstants.LOGDIR0)2 LOGDIR1 (com.linkedin.kafka.cruisecontrol.common.TestConstants.LOGDIR1)2 TOPIC0 (com.linkedin.kafka.cruisecontrol.common.TestConstants.TOPIC0)2 TOPIC1 (com.linkedin.kafka.cruisecontrol.common.TestConstants.TOPIC1)2 TOPIC2 (com.linkedin.kafka.cruisecontrol.common.TestConstants.TOPIC2)2 BrokerCapacityInfo (com.linkedin.kafka.cruisecontrol.config.BrokerCapacityInfo)2 ClusterModel (com.linkedin.kafka.cruisecontrol.model.ClusterModel)2 ReplicaPlacementInfo (com.linkedin.kafka.cruisecontrol.model.ReplicaPlacementInfo)2