diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/CatalogReplicaLoadBalanceSimpleSelector.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/CatalogReplicaLoadBalanceSimpleSelector.java index 01996b34e2e..be5cd88f965 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/CatalogReplicaLoadBalanceSimpleSelector.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/CatalogReplicaLoadBalanceSimpleSelector.java @@ -44,15 +44,15 @@ import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; * balancing algorithm. It maintains a stale location cache for each table. Whenever client looks * up location, it first check if the row is the stale location cache. If yes, the location from * catalog replica is stale, it will go to the primary region to look up update-to-date location; - * otherwise, it will randomly pick up a replica region for lookup. When clients receive - * RegionNotServedException from region servers, it will add these region locations to the stale - * location cache. The stale cache will be cleaned up periodically by a chore.

+ * otherwise, it will randomly pick up a replica region or primary region for lookup. When clients + * receive RegionNotServedException from region servers, it will add these region locations to the + * stale location cache. The stale cache will be cleaned up periodically by a chore.

* - * It follows a simple algorithm to choose a replica to go: + * It follows a simple algorithm to choose a meta replica region (including primary meta) to go: * *
    *
  1. If there is no stale location entry for rows it looks up, it will randomly - * pick a replica region to do lookup.
  2. + * pick a meta replica region (including primary meta) to do lookup. *
  3. If the location from the replica region is stale, client gets RegionNotServedException * from region server, in this case, it will create StaleLocationCacheEntry in * CatalogReplicaLoadBalanceReplicaSimpleSelector.
  4. @@ -139,7 +139,7 @@ class CatalogReplicaLoadBalanceSimpleSelector implements } /** - * Select an random replica id. In case there is no replica region configured, return + * Select an random replica id (including the primary replica id). In case there is no replica region configured, return * the primary replica id. * @return Replica id */ @@ -153,7 +153,7 @@ class CatalogReplicaLoadBalanceSimpleSelector implements if (cachedNumOfReplicas <= 1) { return RegionInfo.DEFAULT_REPLICA_ID; } - return 1 + ThreadLocalRandom.current().nextInt(cachedNumOfReplicas - 1); + return ThreadLocalRandom.current().nextInt(cachedNumOfReplicas); } /** diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCatalogReplicaLoadBalanceSimpleSelector.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCatalogReplicaLoadBalanceSimpleSelector.java index bebc843933e..2da871ca3d2 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCatalogReplicaLoadBalanceSimpleSelector.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestCatalogReplicaLoadBalanceSimpleSelector.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertNotEquals; import java.io.IOException; import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseTestingUtil; @@ -105,9 +106,13 @@ public class TestCatalogReplicaLoadBalanceSimpleSelector { return numOfReplicas; }); - assertNotEquals( - metaSelector.select(TableName.valueOf("test"), EMPTY_START_ROW, RegionLocateType.CURRENT), - RegionReplicaUtil.DEFAULT_REPLICA_ID); + // Loop for 100 times, it should cover all replica ids. + int[] replicaIdCount = new int[numOfMetaReplica]; + IntStream.range(1, 100).forEach(i -> replicaIdCount[metaSelector.select( + TableName.valueOf("test"), EMPTY_START_ROW, RegionLocateType.CURRENT)] ++); + + // Make sure each replica id is returned by select() call, including primary replica id. + IntStream.range(0, numOfMetaReplica).forEach(i -> assertNotEquals(replicaIdCount[i], 0)); // Change to No meta replica HBaseTestingUtil.setReplicas(admin, TableName.META_TABLE_NAME, 1); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestMetaRegionReplicaReplication.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestMetaRegionReplicaReplication.java index 2fcfc29a163..62370496974 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestMetaRegionReplicaReplication.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestMetaRegionReplicaReplication.java @@ -395,6 +395,16 @@ public class TestMetaRegionReplicaReplication { } } + private void primaryIncreaseReplicaIncrease(final long[] before, final long[] after) { + // There are read requests increase for primary meta replica. + assertTrue(after[RegionInfo.DEFAULT_REPLICA_ID] > before[RegionInfo.DEFAULT_REPLICA_ID]); + + // There are read requests incrase for meta replica regions. + for (int i = 1; i < after.length; i++) { + assertTrue(after[i] > before[i]); + } + } + private void getMetaReplicaReadRequests(final Region[] metaRegions, final long[] counters) { int i = 0; for (Region r : metaRegions) { @@ -455,9 +465,8 @@ public class TestMetaRegionReplicaReplication { getMetaReplicaReadRequests(metaRegions, readReqsForMetaReplicasAfterGet); - // There is no read requests increase for primary meta replica. - // For rest of meta replicas, there are more reads against them. - primaryNoChangeReplicaIncrease(readReqsForMetaReplicas, readReqsForMetaReplicasAfterGet); + // There are more reads against all meta replica regions, including the primary region. + primaryIncreaseReplicaIncrease(readReqsForMetaReplicas, readReqsForMetaReplicasAfterGet); // move one of regions so it meta cache may be invalid. HTU.moveRegionAndWait(userRegion.getRegionInfo(), destRs.getServerName());