diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java index 12aca888594..82b218c82d6 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.java @@ -1328,7 +1328,7 @@ public class StochasticLoadBalancer extends BaseLoadBalancer { double cost = 0; do { double current = getCostFromRl(iter.next()); - cost += current - previous; + cost += current >= previous ? current - previous : current; previous = current; } while (iter.hasNext()); return Math.max(0, cost / (regionLoadList.size() - 1)); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java index 910e5d8cd27..a21d8893457 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancer.java @@ -358,6 +358,32 @@ public class TestStochasticLoadBalancer extends BalancerTestBase { assertEquals(2.5, result, 0.01); } + @Test + public void testRegionLoadCostWhenDecrease() { + List regionLoads = new ArrayList<>(); + // test region loads of [1,2,1,4] + for (int i = 1; i < 5; i++) { + int load = i == 3 ? 1 : i; + BalancerRegionLoad regionLoad = mock(BalancerRegionLoad.class); + when(regionLoad.getReadRequestsCount()).thenReturn((long)load); + when(regionLoad.getStorefileSizeMB()).thenReturn(load); + regionLoads.add(regionLoad); + } + + Configuration conf = HBaseConfiguration.create(); + StochasticLoadBalancer.ReadRequestCostFunction readCostFunction = + new StochasticLoadBalancer.ReadRequestCostFunction(conf); + double rateResult = readCostFunction.getRegionLoadCost(regionLoads); + // read requests are treated as a rate, so here is the average rate + assertEquals(1.67, rateResult, 0.01); + + StochasticLoadBalancer.StoreFileCostFunction storeFileCostFunction = + new StochasticLoadBalancer.StoreFileCostFunction(conf); + rateResult = storeFileCostFunction.getRegionLoadCost(regionLoads); + // storefile size cost is simply an average of it's value over time + assertEquals(2.0, rateResult, 0.01); + } + @Test public void testLosingRs() throws Exception { int numNodes = 3;