Index: src/test/java/org/apache/hadoop/hbase/master/TestLoadBalancer.java
===================================================================
--- src/test/java/org/apache/hadoop/hbase/master/TestLoadBalancer.java (revision 1084371)
+++ src/test/java/org/apache/hadoop/hbase/master/TestLoadBalancer.java (working copy)
@@ -39,6 +39,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HServerAddress;
import org.apache.hadoop.hbase.HServerInfo;
@@ -57,7 +59,9 @@
@BeforeClass
public static void beforeAllTests() throws Exception {
- loadBalancer = new LoadBalancer();
+ Configuration conf = HBaseConfiguration.create();
+ conf.set("hbase.regions.slop", "0");
+ loadBalancer = new LoadBalancer(conf);
rand = new Random();
}
Index: src/main/java/org/apache/hadoop/hbase/master/HMaster.java
===================================================================
--- src/main/java/org/apache/hadoop/hbase/master/HMaster.java (revision 1084371)
+++ src/main/java/org/apache/hadoop/hbase/master/HMaster.java (working copy)
@@ -163,7 +163,7 @@
// Instance of the hbase executor service.
ExecutorService executorService;
- private LoadBalancer balancer = new LoadBalancer();
+ private LoadBalancer balancer;
private Thread balancerChore;
// If 'true', the balancer is 'on'. If 'false', the balancer will not run.
private volatile boolean balanceSwitch = true;
@@ -358,6 +358,7 @@
this.assignmentManager = new AssignmentManager(this, serverManager,
this.catalogTracker, this.executorService);
+ this.balancer = new LoadBalancer(conf);
zooKeeper.registerListenerFirst(assignmentManager);
this.regionServerTracker = new RegionServerTracker(zooKeeper, this,
Index: src/main/resources/hbase-default.xml
===================================================================
--- src/main/resources/hbase-default.xml (revision 1084371)
+++ src/main/resources/hbase-default.xml (working copy)
@@ -282,6 +282,13 @@
+ hbase.regions.slop
+ 0
+ Rebalance if regionserver has average + (average * slop) regions.
+ Default is 0% slop
+
+
+
hbase.master.logcleaner.ttl
600000
Maximum time a HLog can stay in the .oldlogdir directory,
Index: src/main/java/org/apache/hadoop/hbase/master/LoadBalancer.java
===================================================================
--- src/main/java/org/apache/hadoop/hbase/master/LoadBalancer.java (revision 1085151)
+++ src/main/java/org/apache/hadoop/hbase/master/LoadBalancer.java (working copy)
@@ -32,6 +32,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
@@ -59,7 +60,15 @@
public class LoadBalancer {
private static final Log LOG = LogFactory.getLog(LoadBalancer.class);
private static final Random RANDOM = new Random(System.currentTimeMillis());
+ // slop for regions
+ private float slop;
+ LoadBalancer(Configuration conf) {
+ this.slop = conf.getFloat("hbase.regions.slop", (float) 0.2);
+ if (slop < 0) slop = 0;
+ else if (slop > 1) slop = 1;
+ }
+
static class RegionPlanComparator implements Comparator {
@Override
public int compare(RegionPlan l, RegionPlan r) {
@@ -165,10 +174,11 @@
// Check if we even need to do any load balancing
float average = (float)numRegions / numServers; // for logging
- int min = numRegions / numServers;
- int max = numRegions % numServers == 0 ? min : min + 1;
- if(serversByLoad.lastKey().getLoad().getNumberOfRegions() <= max &&
- serversByLoad.firstKey().getLoad().getNumberOfRegions() >= min) {
+ // HBASE-3681 check sloppiness first
+ int floor = (int) Math.floor(average * (1 - slop));
+ int ceiling = (int) Math.ceil(average * (1 + slop));
+ if(serversByLoad.lastKey().getLoad().getNumberOfRegions() <= ceiling &&
+ serversByLoad.firstKey().getLoad().getNumberOfRegions() >= floor) {
// Skipped because no server outside (min,max) range
LOG.info("Skipping load balancing. servers=" + numServers + " " +
"regions=" + numRegions + " average=" + average + " " +
@@ -176,6 +186,8 @@
" leastloaded=" + serversByLoad.firstKey().getLoad().getNumberOfRegions());
return null;
}
+ int min = numRegions / numServers;
+ int max = numRegions % numServers == 0 ? min : min + 1;
// Balance the cluster
// TODO: Look at data block locality or a more complex load to do this