From 117c4f0eee18cd96856239a7b9bb47f0a960a0bc Mon Sep 17 00:00:00 2001 From: Kahlil Oppenheimer Date: Tue, 28 Feb 2017 00:33:57 -0500 Subject: [PATCH] Fixed old table skew measure --- .../hbase/master/balancer/BaseLoadBalancer.java | 21 ++++------ .../master/balancer/StochasticLoadBalancer.java | 19 +++++---- .../balancer/TestStochasticLoadBalancer.java | 49 ++++++++++++++++++---- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java index f6ae9af..8986026 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java @@ -739,18 +739,15 @@ public abstract class BaseLoadBalancer implements LoadBalancer { } numRegionsPerServerPerTable[newServer][tableIndex]++; - //check whether this caused maxRegionsPerTable in the new Server to be updated - if (numRegionsPerServerPerTable[newServer][tableIndex] > numMaxRegionsPerTable[tableIndex]) { - numMaxRegionsPerTable[tableIndex] = numRegionsPerServerPerTable[newServer][tableIndex]; - } else if (oldServer >= 0 && (numRegionsPerServerPerTable[oldServer][tableIndex] + 1) - == numMaxRegionsPerTable[tableIndex]) { - //recompute maxRegionsPerTable since the previous value was coming from the old server - for (int serverIndex = 0 ; serverIndex < numRegionsPerServerPerTable.length; serverIndex++) { - if (numRegionsPerServerPerTable[serverIndex][tableIndex] > numMaxRegionsPerTable[tableIndex]) { - numMaxRegionsPerTable[tableIndex] = numRegionsPerServerPerTable[serverIndex][tableIndex]; - } - } - } + // if old server had max num regions, assume (for now) + // max num regions went down since we moved the region + if (oldServer >= 0 && + (numRegionsPerServerPerTable[oldServer][tableIndex] + 1) == numMaxRegionsPerTable[tableIndex]) { + numMaxRegionsPerTable[tableIndex]--; + } + // Now check if new server sets new max + numMaxRegionsPerTable[tableIndex] = + Math.max(numMaxRegionsPerTable[tableIndex], numRegionsPerServerPerTable[newServer][tableIndex]); // update for servers int primary = regionIndexToPrimaryIndex[region]; diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java index 1877ed2..d736bc7 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java @@ -273,14 +273,6 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { @Override protected boolean needsBalance(Cluster cluster) { - ClusterLoadState cs = new ClusterLoadState(cluster.clusterState); - if (cs.getNumServers() < MIN_SERVER_BALANCE) { - if (LOG.isDebugEnabled()) { - LOG.debug("Not running balancer because only " + cs.getNumServers() - + " active regionserver(s)"); - } - return false; - } if (areSomeRegionReplicasColocated(cluster)) { return true; } @@ -307,6 +299,17 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { + minCostNeedBalance); return false; } + + ClusterLoadState cs = new ClusterLoadState(cluster.clusterState); + if (cs.getNumServers() < MIN_SERVER_BALANCE) { + if (LOG.isDebugEnabled()) { + LOG.debug("Not running balancer because only " + cs.getNumServers() + + " active regionserver(s)"); + } + return false; + } + + return true; } diff --git hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java index b9462af..33d95e1 100644 --- hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java +++ hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java @@ -50,6 +50,7 @@ import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.balancer.BaseLoadBalancer.Cluster; import org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer.CandidateGenerator; import org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer.TableSkewCandidateGenerator; +import org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer.LoadCandidateGenerator; import org.apache.hadoop.hbase.testclassification.FlakeyTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.apache.hadoop.hbase.util.Bytes; @@ -239,6 +240,33 @@ public class TestStochasticLoadBalancer extends BalancerTestBase { } @Test + public void testTableSkewCostProperlyDecreases() { + int replication = 1; + Configuration conf = HBaseConfiguration.create(); + StochasticLoadBalancer.CostFunction + costFunction = new StochasticLoadBalancer.TableSkewCostFunction(conf); + CandidateGenerator generator = new LoadCandidateGenerator(); + // Start out with 100 regions on one server and 0 regions on the other + int numNodes = 2; + int numTables = 1; + int numRegions = 100; + int numRegionsPerServer = 0; + + Map> serverMap = createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables); + BaseLoadBalancer.Cluster cluster = new Cluster(serverMap, null, null, null); + costFunction.init(cluster); + double cost = costFunction.cost(); + assertEquals(1.0, cost, .0001); + for (int i = 0; i < 100; i++) { + Cluster.Action action = generator.generate(cluster); + cluster.doAction(action); + costFunction.postAction(action); + cost = costFunction.cost(); + } + assertTrue(cost < 0.5); + } + + @Test public void testRegionLoadCost() { List regionLoads = new ArrayList<>(); for (int i = 1; i < 5; i++) { @@ -265,16 +293,21 @@ public class TestStochasticLoadBalancer extends BalancerTestBase { @Test (timeout=45000) public void testTableSkewCandidateGeneratorConvergesToZero() { int replication = 1; - StochasticLoadBalancer.CostFunction - costFunction = new StochasticLoadBalancer.TableSkewCostFunction(conf); + StochasticLoadBalancer.CostFunction costFunction = + new StochasticLoadBalancer.TableSkewCostFunction(conf); CandidateGenerator generator = new TableSkewCandidateGenerator(); for (int i = 0; i < 5; i++) { - int numNodes = rand.nextInt(100) + 1; // num nodes between 1 - 100 - int numTables = rand.nextInt(100) + 1; // num tables between 1 and 100 - int numRegions = rand.nextInt(numTables * 99) + Math.max(numTables, numNodes); // num regions between max(numTables, numNodes) - numTables*100 - int numRegionsPerServer = rand.nextInt(numRegions / numNodes) + 1; // num regions per server (except one) between 1 and numRegions / numNodes - - Map> serverMap = createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables); + // num nodes between 1 - 100 + int numNodes = rand.nextInt(100) + 1; + // num tables between 1 and 100 + int numTables = rand.nextInt(100) + 1; + // num regions between max(numTables, numNodes) - numTables*100 + int numRegions = rand.nextInt(numTables * 99) + Math.max(numTables, numNodes); + // num regions per server (except one) between 1 and numRegions / numNodes + int numRegionsPerServer = rand.nextInt(numRegions / numNodes) + 1; + + Map> serverMap = + createServerMap(numNodes, numRegions, numRegionsPerServer, replication, numTables); BaseLoadBalancer.Cluster cluster = new Cluster(serverMap, null, null, null); costFunction.init(cluster); double cost = costFunction.cost(); -- 2.10.1 (Apple Git-78)