diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java index aee9eeb63eee..3b433ef602f3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BaseLoadBalancer.java @@ -18,6 +18,7 @@ */ package org.apache.hadoop.hbase.master.balancer; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -1263,7 +1264,7 @@ public Map> roundRobinAssignment(List r return assignments; } - Cluster cluster = createCluster(servers, regions, false); + Cluster cluster = createCluster(servers, regions); List unassignedRegions = new ArrayList<>(); roundRobinAssignment(cluster, regions, unassignedRegions, @@ -1319,8 +1320,22 @@ public Map> roundRobinAssignment(List r return assignments; } - protected Cluster createCluster(List servers, Collection regions, - boolean hasRegionReplica) { + protected Cluster createCluster(List servers, Collection regions) + throws HBaseIOException { + boolean hasRegionReplica = false; + try { + for (RegionInfo regionInfo : regions) { + TableName tableName = regionInfo.getTable(); + if (services != null && + services.getTableDescriptors().get(tableName).getRegionReplication() > 1) { + hasRegionReplica = true; + break; + } + } + } catch (IOException ioe) { + throw new HBaseIOException(ioe); + } + // Get the snapshot of the current assignments for the regions in question, and then create // a cluster out of it. Note that we might have replicas already assigned to some servers // earlier. So we want to get the snapshot to see those assignments, but this will only contain @@ -1380,7 +1395,7 @@ public ServerName randomAssignment(RegionInfo regionInfo, List serve final List finalServers = idleServers.isEmpty() ? servers : idleServers; List regions = Lists.newArrayList(regionInfo); - Cluster cluster = createCluster(finalServers, regions, false); + Cluster cluster = createCluster(finalServers, regions); return randomAssignment(cluster, regionInfo, finalServers); } @@ -1452,21 +1467,9 @@ public Map> retainAssignment(Map entry : regions.entrySet()) { RegionInfo region = entry.getKey(); ServerName oldServerName = entry.getValue(); - // In the current set of regions even if one has region replica let us go with - // getting the entire snapshot - if (this.services != null) { // for tests - AssignmentManager am = this.services.getAssignmentManager(); - if (am != null) { - RegionStates states = am.getRegionStates(); - if (!hasRegionReplica && states != null && states.isReplicaAvailableForRegion(region)) { - hasRegionReplica = true; - } - } - } List localServers = new ArrayList<>(); if (oldServerName != null) { localServers = serversByHostname.get(oldServerName.getHostnameLowerCase()); @@ -1506,7 +1509,7 @@ public Map> retainAssignment(Map 0) { - Cluster cluster = createCluster(servers, regions.keySet(), hasRegionReplica); + Cluster cluster = createCluster(servers, regions.keySet()); for (Map.Entry> entry : assignments.entrySet()) { ServerName sn = entry.getKey(); for (RegionInfo region : entry.getValue()) { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionReplicasWithRestartScenarios.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionReplicasWithRestartScenarios.java index a4c09188ee27..70df61e497e8 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionReplicasWithRestartScenarios.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestRegionReplicasWithRestartScenarios.java @@ -24,10 +24,12 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionReplicaUtil; @@ -37,7 +39,6 @@ import org.apache.hadoop.hbase.testclassification.RegionServerTests; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.RegionSplitter; -import org.apache.hadoop.hdfs.DFSConfigKeys; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -64,31 +65,27 @@ public class TestRegionReplicasWithRestartScenarios { private static final int NB_SERVERS = 3; private Table table; + private TableName tableName; private static final HBaseTestingUtility HTU = new HBaseTestingUtility(); private static final byte[] f = HConstants.CATALOG_FAMILY; @BeforeClass public static void beforeClass() throws Exception { - // Reduce the hdfs block size and prefetch to trigger the file-link reopen - // when the file is moved to archive (e.g. compaction) - HTU.getConfiguration().setInt(DFSConfigKeys.DFS_BLOCK_SIZE_KEY, 8192); - HTU.getConfiguration().setInt(DFSConfigKeys.DFS_CLIENT_READ_PREFETCH_SIZE_KEY, 1); - HTU.getConfiguration().setInt(HConstants.HREGION_MEMSTORE_FLUSH_SIZE, 128 * 1024 * 1024); - HTU.getConfiguration().setInt(">hbase.master.wait.on.regionservers.mintostart", 3); + HTU.getConfiguration().setInt("hbase.master.wait.on.regionservers.mintostart", NB_SERVERS); HTU.startMiniCluster(NB_SERVERS); } @Before public void before() throws IOException { - TableName tableName = TableName.valueOf(this.name.getMethodName()); - // Create table then get the single region for our new table. - this.table = createTableDirectlyFromHTD(tableName); + this.tableName = TableName.valueOf(this.name.getMethodName()); + this.table = createTableDirectlyFromHTD(this.tableName); } @After public void after() throws IOException { this.table.close(); + HTU.deleteTable(this.tableName); } private static Table createTableDirectlyFromHTD(final TableName tableName) throws IOException { @@ -125,6 +122,20 @@ private HRegionServer getTertiaryRS() { @Test public void testRegionReplicasCreated() throws Exception { + assertReplicaDistributed(); + } + + @Test + public void testWhenRestart() throws Exception { + ServerName serverName = getRS().getServerName(); + HTU.getHBaseCluster().stopRegionServer(serverName); + HTU.getHBaseCluster().waitForRegionServerToStop(serverName, 60000); + HTU.getHBaseCluster().startRegionServerAndWait(60000); + HTU.waitTableAvailable(this.tableName); + assertReplicaDistributed(); + } + + private void assertReplicaDistributed() throws Exception { Collection onlineRegions = getRS().getOnlineRegionsLocalContext(); boolean res = checkDuplicates(onlineRegions); assertFalse(res); @@ -150,7 +161,7 @@ private boolean checkDuplicates(Collection onlineRegions3) throws Excep RegionReplicaUtil.getRegionInfoForDefaultReplica(actualRegion.getRegionInfo()))) { i++; if (i > 1) { - LOG.info("Duplicate found " + actualRegion.getRegionInfo() + " " + + LOG.warn("Duplicate found {} and {}", actualRegion.getRegionInfo(), region.getRegionInfo()); assertTrue(Bytes.equals(region.getRegionInfo().getStartKey(), actualRegion.getRegionInfo().getStartKey()));