From 6f28eac9952b01abb0fdc9803b9f548665ca4643 Mon Sep 17 00:00:00 2001 From: Dhruv Parthasarathy Date: Thu, 1 Aug 2013 17:28:32 -0700 Subject: [PATCH] fixed problem of balancer ignoring home server --- .../metamx/druid/master/BalancerStrategy.java | 4 +- .../druid/master/CostBalancerStrategy.java | 54 ++++++++++++------- .../druid/master/DruidMasterBalancer.java | 2 +- .../druid/master/RandomBalancerStrategy.java | 24 ++++++++- .../metamx/druid/master/rules/LoadRule.java | 2 +- 5 files changed, 61 insertions(+), 25 deletions(-) diff --git a/server/src/main/java/com/metamx/druid/master/BalancerStrategy.java b/server/src/main/java/com/metamx/druid/master/BalancerStrategy.java index ef167eecfa3..84944114b49 100644 --- a/server/src/main/java/com/metamx/druid/master/BalancerStrategy.java +++ b/server/src/main/java/com/metamx/druid/master/BalancerStrategy.java @@ -25,7 +25,9 @@ import java.util.List; public interface BalancerStrategy { - public ServerHolder findNewSegmentHome(final DataSegment proposalSegment, final List serverHolders); + public ServerHolder findNewSegmentHomeBalancer(final DataSegment proposalSegment, final List serverHolders); + + public ServerHolder findNewSegmentHomeReplicator(final DataSegment proposalSegment, final List serverHolders); public BalancerSegmentHolder pickSegmentToMove(final List serverHolders); diff --git a/server/src/main/java/com/metamx/druid/master/CostBalancerStrategy.java b/server/src/main/java/com/metamx/druid/master/CostBalancerStrategy.java index ae8bc0372ae..18930b97e45 100644 --- a/server/src/main/java/com/metamx/druid/master/CostBalancerStrategy.java +++ b/server/src/main/java/com/metamx/druid/master/CostBalancerStrategy.java @@ -43,14 +43,24 @@ public class CostBalancerStrategy implements BalancerStrategy } @Override - public ServerHolder findNewSegmentHome( + public ServerHolder findNewSegmentHomeReplicator( DataSegment proposalSegment, List serverHolders ) { - return computeCosts(proposalSegment, serverHolders).rhs; + return chooseBestServer(proposalSegment, serverHolders, false).rhs; } + @Override + public ServerHolder findNewSegmentHomeBalancer( + DataSegment proposalSegment, List serverHolders + ) + { + return chooseBestServer(proposalSegment, serverHolders, true).rhs; + } + + + /** * For assignment, we want to move to the lowest cost server that isn't already serving the segment. * @@ -60,9 +70,10 @@ public class CostBalancerStrategy implements BalancerStrategy * @return A ServerHolder with the new home for a segment. */ - private Pair computeCosts( + private Pair chooseBestServer( final DataSegment proposalSegment, - final Iterable serverHolders + final Iterable serverHolders, + boolean includeCurrentServer ) { @@ -84,26 +95,29 @@ public class CostBalancerStrategy implements BalancerStrategy final long proposalSegmentSize = proposalSegment.getSize(); for (ServerHolder server : serverHolders) { - /** Don't calculate cost if the server doesn't have enough space or is loading the segment */ - if (proposalSegmentSize > server.getAvailableSize() || server.isLoadingSegment(proposalSegment)) { - continue; - } + if (includeCurrentServer || !server.isServingSegment(proposalSegment)) + { + /** Don't calculate cost if the server doesn't have enough space or is loading the segment */ + if (proposalSegmentSize > server.getAvailableSize() || server.isLoadingSegment(proposalSegment)) { + continue; + } - /** The contribution to the total cost of a given server by proposing to move the segment to that server is... */ - double cost = 0f; - /** the sum of the costs of other (exclusive of the proposalSegment) segments on the server */ - for (DataSegment segment : server.getServer().getSegments().values()) { - if (!proposalSegment.equals(segment)) { + /** The contribution to the total cost of a given server by proposing to move the segment to that server is... */ + double cost = 0f; + /** the sum of the costs of other (exclusive of the proposalSegment) segments on the server */ + for (DataSegment segment : server.getServer().getSegments().values()) { + if (!proposalSegment.equals(segment)) { + cost += computeJointSegmentCosts(proposalSegment, segment); + } + } + /** plus the costs of segments that will be loaded */ + for (DataSegment segment : server.getPeon().getSegmentsToLoad()) { cost += computeJointSegmentCosts(proposalSegment, segment); } - } - /** plus the costs of segments that will be loaded */ - for (DataSegment segment : server.getPeon().getSegmentsToLoad()) { - cost += computeJointSegmentCosts(proposalSegment, segment); - } - if (cost < bestServer.lhs && !server.isServingSegment(proposalSegment)) { - bestServer = Pair.of(cost, server); + if (cost < bestServer.lhs) { + bestServer = Pair.of(cost, server); + } } } diff --git a/server/src/main/java/com/metamx/druid/master/DruidMasterBalancer.java b/server/src/main/java/com/metamx/druid/master/DruidMasterBalancer.java index 9b3dd1cb132..2745d079410 100644 --- a/server/src/main/java/com/metamx/druid/master/DruidMasterBalancer.java +++ b/server/src/main/java/com/metamx/druid/master/DruidMasterBalancer.java @@ -116,7 +116,7 @@ public class DruidMasterBalancer implements DruidMasterHelper final BalancerSegmentHolder segmentToMove = strategy.pickSegmentToMove(serverHolderList); if (segmentToMove != null && params.getAvailableSegments().contains(segmentToMove.getSegment())) { - final ServerHolder holder = strategy.findNewSegmentHome(segmentToMove.getSegment(), serverHolderList); + final ServerHolder holder = strategy.findNewSegmentHomeBalancer(segmentToMove.getSegment(), serverHolderList); if (holder != null) { moveSegment(segmentToMove, holder.getServer(), params); diff --git a/server/src/main/java/com/metamx/druid/master/RandomBalancerStrategy.java b/server/src/main/java/com/metamx/druid/master/RandomBalancerStrategy.java index b1cff01d782..d953b69b3db 100644 --- a/server/src/main/java/com/metamx/druid/master/RandomBalancerStrategy.java +++ b/server/src/main/java/com/metamx/druid/master/RandomBalancerStrategy.java @@ -29,11 +29,31 @@ public class RandomBalancerStrategy implements BalancerStrategy private final ReservoirSegmentSampler sampler = new ReservoirSegmentSampler(); @Override - public ServerHolder findNewSegmentHome( + public ServerHolder findNewSegmentHomeReplicator( DataSegment proposalSegment, List serverHolders ) { - return serverHolders.get(new Random().nextInt(serverHolders.size())); + if (serverHolders.size()==1) + { + return null; + } + else + { + ServerHolder holder = serverHolders.get(new Random().nextInt(serverHolders.size())); + while (holder.isServingSegment(proposalSegment)) + { + holder = serverHolders.get(new Random().nextInt(serverHolders.size())); + } + return holder; + } + } + + @Override + public ServerHolder findNewSegmentHomeBalancer( + DataSegment proposalSegment, List serverHolders + ) + { + return null; //To change body of implemented methods use File | Settings | File Templates. } @Override diff --git a/server/src/main/java/com/metamx/druid/master/rules/LoadRule.java b/server/src/main/java/com/metamx/druid/master/rules/LoadRule.java index 1cf0212a950..64aa3dfaff0 100644 --- a/server/src/main/java/com/metamx/druid/master/rules/LoadRule.java +++ b/server/src/main/java/com/metamx/druid/master/rules/LoadRule.java @@ -97,7 +97,7 @@ public abstract class LoadRule implements Rule break; } - final ServerHolder holder = strategy.findNewSegmentHome(segment, serverHolderList); + final ServerHolder holder = strategy.findNewSegmentHomeReplicator(segment, serverHolderList); if (holder == null) { log.warn(