HBASE-19021 Restore a few important missing logics for balancer in 2.0

Signed-off-by: Jerry He <jerryjch@apache.org>
This commit is contained in:
Jerry He 2017-10-24 07:53:17 -07:00
parent 3f9ea98c92
commit a49850e5c3
4 changed files with 35 additions and 7 deletions

View File

@ -1421,16 +1421,19 @@ public class HMaster extends HRegionServer implements MasterServices {
} }
} }
boolean isByTable = getConfiguration().getBoolean("hbase.master.loadbalance.bytable", false);
Map<TableName, Map<ServerName, List<RegionInfo>>> assignmentsByTable = Map<TableName, Map<ServerName, List<RegionInfo>>> assignmentsByTable =
this.assignmentManager.getRegionStates().getAssignmentsByTable(); this.assignmentManager.getRegionStates().getAssignmentsByTable(!isByTable);
List<RegionPlan> plans = new ArrayList<>(); List<RegionPlan> plans = new ArrayList<>();
//Give the balancer the current cluster state. //Give the balancer the current cluster state.
this.balancer.setClusterStatus(getClusterStatus()); this.balancer.setClusterStatus(getClusterStatus());
this.balancer.setClusterLoad( this.balancer.setClusterLoad(assignmentsByTable);
this.assignmentManager.getRegionStates().getAssignmentsByTable());
for (Map<ServerName, List<RegionInfo>> serverMap : assignmentsByTable.values()) {
serverMap.keySet().removeAll(this.serverManager.getDrainingServersList());
}
for (Entry<TableName, Map<ServerName, List<RegionInfo>>> e : assignmentsByTable.entrySet()) { for (Entry<TableName, Map<ServerName, List<RegionInfo>>> e : assignmentsByTable.entrySet()) {
List<RegionPlan> partialPlans = this.balancer.balanceCluster(e.getKey(), e.getValue()); List<RegionPlan> partialPlans = this.balancer.balanceCluster(e.getKey(), e.getValue());
if (partialPlans != null) plans.addAll(partialPlans); if (partialPlans != null) plans.addAll(partialPlans);

View File

@ -756,6 +756,14 @@ public class RegionStates {
serverResult.add(node.getRegionInfo()); serverResult.add(node.getRegionInfo());
} }
// Add online servers with no assignment for the table.
for (Map<ServerName, List<RegionInfo>> table: result.values()) {
for (ServerName svr : serverMap.keySet()) {
if (!table.containsKey(svr)) {
table.put(svr, new ArrayList<RegionInfo>());
}
}
}
return result; return result;
} }

View File

@ -172,6 +172,7 @@ implements ServerProcedureInterface {
break; break;
case SERVER_CRASH_FINISH: case SERVER_CRASH_FINISH:
services.getAssignmentManager().getRegionStates().removeServer(serverName);
services.getServerManager().getDeadServers().finish(serverName); services.getServerManager().getDeadServers().finish(serverName);
return Flow.NO_MORE_STATE; return Flow.NO_MORE_STATE;

View File

@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -53,9 +54,9 @@ import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
/** /**
* Test whether region re-balancing works. (HBASE-71) * Test whether region re-balancing works. (HBASE-71)
* The test only works for cluster wide balancing, not per table wide.
* Increase the margin a little to make StochasticLoadBalancer result acceptable.
*/ */
@Ignore // This is broken since new RegionServers does proper average of regions
// and because Master is treated as a regionserver though it hosts two regions only.
@Category({FlakeyTests.class, LargeTests.class}) @Category({FlakeyTests.class, LargeTests.class})
@RunWith(value = Parameterized.class) @RunWith(value = Parameterized.class)
public class TestRegionRebalancing { public class TestRegionRebalancing {
@ -131,6 +132,7 @@ public class TestRegionRebalancing {
// add a region server - total of 3 // add a region server - total of 3
LOG.info("Started third server=" + LOG.info("Started third server=" +
UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName());
waitForAllRegionsAssigned();
assert(UTIL.getHBaseCluster().getMaster().balance() == true); assert(UTIL.getHBaseCluster().getMaster().balance() == true);
assertRegionsAreBalanced(); assertRegionsAreBalanced();
@ -147,12 +149,14 @@ public class TestRegionRebalancing {
LOG.info("Added fourth server=" + LOG.info("Added fourth server=" +
UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName()); UTIL.getHBaseCluster().startRegionServer().getRegionServer().getServerName());
waitOnCrashProcessing(); waitOnCrashProcessing();
waitForAllRegionsAssigned();
assert(UTIL.getHBaseCluster().getMaster().balance() == true); assert(UTIL.getHBaseCluster().getMaster().balance() == true);
assertRegionsAreBalanced(); assertRegionsAreBalanced();
for (int i = 0; i < 6; i++){ for (int i = 0; i < 6; i++){
LOG.info("Adding " + (i + 5) + "th region server"); LOG.info("Adding " + (i + 5) + "th region server");
UTIL.getHBaseCluster().startRegionServer(); UTIL.getHBaseCluster().startRegionServer();
} }
waitForAllRegionsAssigned();
assert(UTIL.getHBaseCluster().getMaster().balance() == true); assert(UTIL.getHBaseCluster().getMaster().balance() == true);
assertRegionsAreBalanced(); assertRegionsAreBalanced();
regionLocator.close(); regionLocator.close();
@ -188,9 +192,14 @@ public class TestRegionRebalancing {
long regionCount = UTIL.getMiniHBaseCluster().countServedRegions(); long regionCount = UTIL.getMiniHBaseCluster().countServedRegions();
List<HRegionServer> servers = getOnlineRegionServers(); List<HRegionServer> servers = getOnlineRegionServers();
double avg = UTIL.getHBaseCluster().getMaster().getAverageLoad(); double avg = (double)regionCount / (double)servers.size();
int avgLoadPlusSlop = (int)Math.ceil(avg * (1 + slop)); int avgLoadPlusSlop = (int)Math.ceil(avg * (1 + slop));
int avgLoadMinusSlop = (int)Math.floor(avg * (1 - slop)) - 1; int avgLoadMinusSlop = (int)Math.floor(avg * (1 - slop)) - 1;
// Increase the margin a little to accommodate StochasticLoadBalancer
if (this.balancerName.contains("StochasticLoadBalancer")) {
avgLoadPlusSlop++;
avgLoadMinusSlop--;
}
LOG.debug("There are " + servers.size() + " servers and " + regionCount LOG.debug("There are " + servers.size() + " servers and " + regionCount
+ " regions. Load Average: " + avg + " low border: " + avgLoadMinusSlop + " regions. Load Average: " + avg + " low border: " + avgLoadMinusSlop
+ ", up border: " + avgLoadPlusSlop + "; attempt: " + i); + ", up border: " + avgLoadPlusSlop + "; attempt: " + i);
@ -250,13 +259,20 @@ public class TestRegionRebalancing {
*/ */
private void waitForAllRegionsAssigned() throws IOException { private void waitForAllRegionsAssigned() throws IOException {
int totalRegions = HBaseTestingUtility.KEYS.length; int totalRegions = HBaseTestingUtility.KEYS.length;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
while (UTIL.getMiniHBaseCluster().countServedRegions() < totalRegions) { while (UTIL.getMiniHBaseCluster().countServedRegions() < totalRegions) {
// while (!cluster.getMaster().allRegionsAssigned()) { // while (!cluster.getMaster().allRegionsAssigned()) {
LOG.debug("Waiting for there to be "+ totalRegions +" regions, but there are " LOG.debug("Waiting for there to be "+ totalRegions +" regions, but there are "
+ UTIL.getMiniHBaseCluster().countServedRegions() + " right now."); + UTIL.getMiniHBaseCluster().countServedRegions() + " right now.");
try { try {
Thread.sleep(200); Thread.sleep(200);
} catch (InterruptedException e) {} } catch (InterruptedException e) {
throw new InterruptedIOException();
}
} }
UTIL.waitUntilNoRegionsInTransition(); UTIL.waitUntilNoRegionsInTransition();
} }