Search in sources :

Example 21 with ServerHolder

use of org.apache.druid.server.coordinator.ServerHolder in project druid by druid-io.

the class BalanceSegments method balanceTier.

private void balanceTier(DruidCoordinatorRuntimeParams params, String tier, SortedSet<ServerHolder> servers, CoordinatorStats stats) {
    if (params.getUsedSegments().size() == 0) {
        log.info("Metadata segments are not available. Cannot balance.");
        // suppress emit zero stats
        return;
    }
    currentlyMovingSegments.computeIfAbsent(tier, t -> new ConcurrentHashMap<>());
    if (!currentlyMovingSegments.get(tier).isEmpty()) {
        reduceLifetimes(tier);
        log.info("[%s]: Still waiting on %,d segments to be moved. Skipping balance.", tier, currentlyMovingSegments.get(tier).size());
        // suppress emit zero stats
        return;
    }
    /*
      Take as many segments from decommissioning servers as decommissioningMaxPercentOfMaxSegmentsToMove allows and find
      the best location for them on active servers. After that, balance segments within active servers pool.
     */
    Map<Boolean, List<ServerHolder>> partitions = servers.stream().collect(Collectors.partitioningBy(ServerHolder::isDecommissioning));
    final List<ServerHolder> decommissioningServers = partitions.get(true);
    final List<ServerHolder> activeServers = partitions.get(false);
    log.info("Found %d active servers, %d decommissioning servers", activeServers.size(), decommissioningServers.size());
    if ((decommissioningServers.isEmpty() && activeServers.size() <= 1) || activeServers.isEmpty()) {
        log.warn("[%s]: insufficient active servers. Cannot balance.", tier);
        // suppress emit zero stats
        return;
    }
    int numSegments = 0;
    for (ServerHolder sourceHolder : servers) {
        numSegments += sourceHolder.getServer().getNumSegments();
    }
    if (numSegments == 0) {
        log.info("No segments found. Cannot balance.");
        // suppress emit zero stats
        return;
    }
    final int maxSegmentsToMove = Math.min(params.getCoordinatorDynamicConfig().getMaxSegmentsToMove(), numSegments);
    // Prioritize moving segments from decomissioning servers.
    int decommissioningMaxPercentOfMaxSegmentsToMove = params.getCoordinatorDynamicConfig().getDecommissioningMaxPercentOfMaxSegmentsToMove();
    int maxSegmentsToMoveFromDecommissioningNodes = (int) Math.ceil(maxSegmentsToMove * (decommissioningMaxPercentOfMaxSegmentsToMove / 100.0));
    log.info("Processing %d segments for moving from decommissioning servers", maxSegmentsToMoveFromDecommissioningNodes);
    Pair<Integer, Integer> decommissioningResult = balanceServers(params, decommissioningServers, activeServers, maxSegmentsToMoveFromDecommissioningNodes);
    // After moving segments from decomissioning servers, move the remaining segments from the rest of the servers.
    int maxGeneralSegmentsToMove = maxSegmentsToMove - decommissioningResult.lhs;
    log.info("Processing %d segments for balancing between active servers", maxGeneralSegmentsToMove);
    Pair<Integer, Integer> generalResult = balanceServers(params, activeServers, activeServers, maxGeneralSegmentsToMove);
    int moved = generalResult.lhs + decommissioningResult.lhs;
    int unmoved = generalResult.rhs + decommissioningResult.rhs;
    if (unmoved == maxSegmentsToMove) {
        // Cluster should be alive and constantly adjusting
        log.info("No good moves found in tier [%s]", tier);
    }
    stats.addToTieredStat("unmovedCount", tier, unmoved);
    stats.addToTieredStat("movedCount", tier, moved);
    if (params.getCoordinatorDynamicConfig().emitBalancingStats()) {
        final BalancerStrategy strategy = params.getBalancerStrategy();
        strategy.emitStats(tier, stats, Lists.newArrayList(servers));
    }
    log.info("[%s]: Segments Moved: [%d] Segments Let Alone: [%d]", tier, moved, unmoved);
}
Also used : BalancerStrategy(org.apache.druid.server.coordinator.BalancerStrategy) ServerHolder(org.apache.druid.server.coordinator.ServerHolder) List(java.util.List)

Example 22 with ServerHolder

use of org.apache.druid.server.coordinator.ServerHolder in project druid by druid-io.

the class LoadRule method drop.

/**
 * @param stats {@link CoordinatorStats} to accumulate assignment statistics.
 */
private void drop(final DruidCoordinatorRuntimeParams params, final DataSegment segment, final CoordinatorStats stats) {
    final DruidCluster druidCluster = params.getDruidCluster();
    // This enforces that loading is completed before we attempt to drop stuffs as a safety measure.
    if (loadingInProgress(druidCluster)) {
        log.info("Loading in progress, skipping drop until loading is complete");
        return;
    }
    for (final Object2IntMap.Entry<String> entry : currentReplicants.object2IntEntrySet()) {
        final String tier = entry.getKey();
        final NavigableSet<ServerHolder> holders = druidCluster.getHistoricalsByTier(tier);
        final int numDropped;
        if (holders == null) {
            log.makeAlert("No holders found for tier[%s]", tier).emit();
            numDropped = 0;
        } else {
            final int currentReplicantsInTier = entry.getIntValue();
            final int numToDrop = currentReplicantsInTier - targetReplicants.getOrDefault(tier, 0);
            if (numToDrop > 0) {
                numDropped = dropForTier(numToDrop, holders, segment, params.getBalancerStrategy());
            } else {
                numDropped = 0;
            }
        }
        stats.addToTieredStat(DROPPED_COUNT, tier, numDropped);
    }
}
Also used : ServerHolder(org.apache.druid.server.coordinator.ServerHolder) Object2IntMap(it.unimi.dsi.fastutil.objects.Object2IntMap) DruidCluster(org.apache.druid.server.coordinator.DruidCluster)

Example 23 with ServerHolder

use of org.apache.druid.server.coordinator.ServerHolder in project druid by druid-io.

the class LoadRule method assignPrimary.

/**
 * Iterates through each tier and find the respective segment homes; with the found segment homes, selects the one
 * with the highest priority to be the holder for the primary replica.
 */
@Nullable
private ServerHolder assignPrimary(final DruidCoordinatorRuntimeParams params, final DataSegment segment) {
    ServerHolder topCandidate = null;
    for (final Object2IntMap.Entry<String> entry : targetReplicants.object2IntEntrySet()) {
        final int targetReplicantsInTier = entry.getIntValue();
        // sanity check: target number of replicants should be more than zero.
        if (targetReplicantsInTier <= 0) {
            continue;
        }
        final String tier = entry.getKey();
        String noAvailability = StringUtils.format("No available [%s] servers or node capacity to assign primary segment[%s]! Expected Replicants[%d]", tier, segment.getId(), targetReplicantsInTier);
        final List<ServerHolder> holders = getFilteredHolders(tier, params.getDruidCluster(), createLoadQueueSizeLimitingPredicate(params));
        // no holders satisfy the predicate
        if (holders.isEmpty()) {
            log.warn(noAvailability);
            continue;
        }
        final ServerHolder candidate = params.getBalancerStrategy().findNewSegmentHomeReplicator(segment, holders);
        if (candidate == null) {
            log.warn(noAvailability);
        } else {
            // cache the result for later use.
            strategyCache.put(tier, candidate);
            if (topCandidate == null || candidate.getServer().getPriority() > topCandidate.getServer().getPriority()) {
                topCandidate = candidate;
            }
        }
    }
    if (topCandidate != null) {
        // remove tier for primary replica
        strategyCache.remove(topCandidate.getServer().getTier());
        log.info("Assigning 'primary' for segment [%s] to server [%s] in tier [%s]", segment.getId(), topCandidate.getServer().getName(), topCandidate.getServer().getTier());
        topCandidate.getPeon().loadSegment(segment, null);
    }
    return topCandidate;
}
Also used : ServerHolder(org.apache.druid.server.coordinator.ServerHolder) Object2IntMap(it.unimi.dsi.fastutil.objects.Object2IntMap) Nullable(javax.annotation.Nullable)

Example 24 with ServerHolder

use of org.apache.druid.server.coordinator.ServerHolder in project druid by druid-io.

the class LoadRuleTest method testLoad.

@Test
public void testLoad() {
    EasyMock.expect(throttler.canCreateReplicant(EasyMock.anyString())).andReturn(true).anyTimes();
    final LoadQueuePeon mockPeon = createEmptyPeon();
    mockPeon.loadSegment(EasyMock.anyObject(), EasyMock.anyObject());
    EasyMock.expectLastCall().atLeastOnce();
    LoadRule rule = createLoadRule(ImmutableMap.of("hot", 1, DruidServer.DEFAULT_TIER, 2));
    final DataSegment segment = createDataSegment("foo");
    throttler.registerReplicantCreation(DruidServer.DEFAULT_TIER, segment.getId(), "hostNorm");
    EasyMock.expectLastCall().once();
    EasyMock.expect(mockBalancerStrategy.findNewSegmentHomeReplicator(EasyMock.anyObject(), EasyMock.anyObject())).andDelegateTo(balancerStrategy).times(3);
    EasyMock.replay(throttler, mockPeon, mockBalancerStrategy);
    DruidCluster druidCluster = DruidClusterBuilder.newBuilder().addTier("hot", new ServerHolder(new DruidServer("serverHot", "hostHot", null, 1000, ServerType.HISTORICAL, "hot", 1).toImmutableDruidServer(), mockPeon)).addTier(DruidServer.DEFAULT_TIER, new ServerHolder(new DruidServer("serverNorm", "hostNorm", null, 1000, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 0).toImmutableDruidServer(), mockPeon)).build();
    CoordinatorStats stats = rule.run(null, makeCoordinatorRuntimeParams(druidCluster, segment), segment);
    Assert.assertEquals(1L, stats.getTieredStat(LoadRule.ASSIGNED_COUNT, "hot"));
    Assert.assertEquals(1L, stats.getTieredStat(LoadRule.ASSIGNED_COUNT, DruidServer.DEFAULT_TIER));
    EasyMock.verify(throttler, mockPeon, mockBalancerStrategy);
}
Also used : CoordinatorStats(org.apache.druid.server.coordinator.CoordinatorStats) ServerHolder(org.apache.druid.server.coordinator.ServerHolder) LoadQueuePeon(org.apache.druid.server.coordinator.LoadQueuePeon) DruidServer(org.apache.druid.client.DruidServer) ImmutableDruidServer(org.apache.druid.client.ImmutableDruidServer) DruidCluster(org.apache.druid.server.coordinator.DruidCluster) DataSegment(org.apache.druid.timeline.DataSegment) Test(org.junit.Test)

Example 25 with ServerHolder

use of org.apache.druid.server.coordinator.ServerHolder in project druid by druid-io.

the class LoadRuleTest method testLoadWithNonExistentTier.

@Test
public void testLoadWithNonExistentTier() {
    final LoadQueuePeon mockPeon = createEmptyPeon();
    mockPeon.loadSegment(EasyMock.anyObject(), EasyMock.anyObject());
    EasyMock.expectLastCall().atLeastOnce();
    EasyMock.expect(mockBalancerStrategy.findNewSegmentHomeReplicator(EasyMock.anyObject(), EasyMock.anyObject())).andDelegateTo(balancerStrategy).times(1);
    EasyMock.replay(throttler, mockPeon, mockBalancerStrategy);
    LoadRule rule = createLoadRule(ImmutableMap.of("nonExistentTier", 1, "hot", 1));
    DruidCluster druidCluster = DruidClusterBuilder.newBuilder().addTier("hot", new ServerHolder(new DruidServer("serverHot", "hostHot", null, 1000, ServerType.HISTORICAL, "hot", 0).toImmutableDruidServer(), mockPeon)).build();
    final DataSegment segment = createDataSegment("foo");
    CoordinatorStats stats = rule.run(null, CoordinatorRuntimeParamsTestHelpers.newBuilder().withDruidCluster(druidCluster).withSegmentReplicantLookup(SegmentReplicantLookup.make(new DruidCluster(), false)).withReplicationManager(throttler).withBalancerStrategy(mockBalancerStrategy).withUsedSegmentsInTest(segment).build(), segment);
    Assert.assertEquals(1L, stats.getTieredStat(LoadRule.ASSIGNED_COUNT, "hot"));
    EasyMock.verify(throttler, mockPeon, mockBalancerStrategy);
}
Also used : CoordinatorStats(org.apache.druid.server.coordinator.CoordinatorStats) ServerHolder(org.apache.druid.server.coordinator.ServerHolder) LoadQueuePeon(org.apache.druid.server.coordinator.LoadQueuePeon) DruidServer(org.apache.druid.client.DruidServer) ImmutableDruidServer(org.apache.druid.client.ImmutableDruidServer) DruidCluster(org.apache.druid.server.coordinator.DruidCluster) DataSegment(org.apache.druid.timeline.DataSegment) Test(org.junit.Test)

Aggregations

ServerHolder (org.apache.druid.server.coordinator.ServerHolder)32 CoordinatorStats (org.apache.druid.server.coordinator.CoordinatorStats)22 DataSegment (org.apache.druid.timeline.DataSegment)22 DruidCluster (org.apache.druid.server.coordinator.DruidCluster)18 Test (org.junit.Test)16 DruidServer (org.apache.druid.client.DruidServer)15 ImmutableDruidServer (org.apache.druid.client.ImmutableDruidServer)15 LoadQueuePeon (org.apache.druid.server.coordinator.LoadQueuePeon)15 DruidCoordinatorRuntimeParams (org.apache.druid.server.coordinator.DruidCoordinatorRuntimeParams)7 LoadQueuePeonTester (org.apache.druid.server.coordinator.LoadQueuePeonTester)5 HashMap (java.util.HashMap)4 Object2IntMap (it.unimi.dsi.fastutil.objects.Object2IntMap)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 ServerType (org.apache.druid.server.coordination.ServerType)3 DruidCoordinator (org.apache.druid.server.coordinator.DruidCoordinator)3 SegmentId (org.apache.druid.timeline.SegmentId)3 Object2LongMap (it.unimi.dsi.fastutil.objects.Object2LongMap)2 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2