Index: src/main/java/org/apache/hadoop/hbase/master/HMaster.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 1079088) +++ src/main/java/org/apache/hadoop/hbase/master/HMaster.java (working copy) @@ -863,8 +863,15 @@ region.getLog().closeAndDelete(); } - // 5. Trigger immediate assignment of the regions in round-robin fashion + // 5. see if there're idle region servers which don't carry any regions List servers = serverManager.getOnlineServersList(); + Map> assignments = null; + assignments = this.assignmentManager.getAssignments(); + if (servers.size() > assignments.size()) { + balance(); + } + + // 6. Trigger immediate assignment of the regions in round-robin fashion try { this.assignmentManager.assignUserRegions(Arrays.asList(newRegions), servers); } catch (InterruptedException ie) { @@ -872,7 +879,7 @@ throw new IOException(ie); } - // 5. If sync, wait for assignment of regions + // 7. If sync, wait for assignment of regions if(sync) { LOG.debug("Waiting for " + newRegions.length + " region(s) to be " + "assigned before returning"); Index: src/main/java/org/apache/hadoop/hbase/master/LoadBalancer.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/master/LoadBalancer.java (revision 1079088) +++ src/main/java/org/apache/hadoop/hbase/master/LoadBalancer.java (working copy) @@ -60,6 +60,17 @@ private static final Log LOG = LogFactory.getLog(LoadBalancer.class); private static final Random RANDOM = new Random(System.currentTimeMillis()); + static class RegionInfoComparator implements Comparator { + @Override + public int compare(HRegionInfo l, HRegionInfo r) { + long diff = r.getRegionId() - l.getRegionId(); + if (diff < 0) return -1; + if (diff > 0) return 1; + return 0; + } + } + static RegionInfoComparator riComparator = new RegionInfoComparator(); + static class RegionPlanComparator implements Comparator { @Override public int compare(RegionPlan l, RegionPlan r) { @@ -180,10 +191,11 @@ // Balance the cluster // TODO: Look at data block locality or a more complex load to do this List regionsToMove = new ArrayList(); - int regionidx = 0; // track the index in above list for setting destination // Walk down most loaded, pruning each to the max int serversOverloaded = 0; + // flag used to fetch regions from head and tail of list, alternately + boolean fetchFromTail = true; Map serverBalanceInfo = new TreeMap(); for(Map.Entry> server : @@ -195,11 +207,17 @@ break; } serversOverloaded++; - List regions = randomize(server.getValue()); + List regions = server.getValue(); + Collections.sort(regions, riComparator); int numToOffload = Math.min(regionCount - max, regions.size()); int numTaken = 0; - for (int i = regions.size() - 1; i >= 0; i--) { - HRegionInfo hri = regions.get(i); + int limit = (int) Math.floor((regions.size()-1.0)/2.0); + for (int i = 0; i <= limit; fetchFromTail = !fetchFromTail) { + HRegionInfo hri = regions.get(i); // fetch from head + if (fetchFromTail) { + hri = regions.get(regions.size() - 1 - i); + i++; + } // Don't rebalance meta regions. if (hri.isMetaRegion()) continue; regionsToMove.add(new RegionPlan(hri, serverInfo, null)); @@ -209,10 +227,14 @@ serverBalanceInfo.put(serverInfo, new BalanceInfo(numToOffload, (-1)*numTaken)); } - + // put young regions at the beginning of regionsToMove + // Collections.sort(regionsToMove, rpComparator); + // Walk down least loaded, filling each to the min int serversUnderloaded = 0; // number of servers that get new regions int neededRegions = 0; // number of regions needed to bring all up to min + int regionidx = 0; // track the index in above list for setting destination for(Map.Entry> server : serversByLoad.entrySet()) { int regionCount = server.getKey().getLoad().getNumberOfRegions(); @@ -325,7 +347,7 @@ } // All done! - LOG.info("Calculated a load balance in " + (endTime-startTime) + "ms. " + + LOG.info("Done. Calculated a load balance in " + (endTime-startTime) + "ms. " + "Moving " + regionsToMove.size() + " regions off of " + serversOverloaded + " overloaded servers onto " + serversUnderloaded + " less loaded servers");