diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java index 847d4f0855e..2b9c0bdccc3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStates.java @@ -37,9 +37,11 @@ import org.apache.hadoop.hbase.HRegionLocation; 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; import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.RegionState.State; import org.apache.hadoop.hbase.util.Bytes; +import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil; import org.apache.yetus.audience.InterfaceAudience; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -772,6 +774,26 @@ public class RegionStates { return serverNode; } + public boolean isReplicaAvailableForRegion(final RegionInfo info) { + // if the region info itself is a replica return true. + if (!RegionReplicaUtil.isDefaultReplica(info)) { + return true; + } + // iterate the regionsMap for the given region name. If there are replicas it should + // list them in order. + for (RegionStateNode node : regionsMap.tailMap(info.getRegionName()).values()) { + if (!node.getTable().equals(info.getTable()) + || !ServerRegionReplicaUtil.isReplicasForSameRegion(info, node.getRegionInfo())) { + break; + } else if (!RegionReplicaUtil.isDefaultReplica(node.getRegionInfo())) { + // we have replicas + return true; + } + } + // we don have replicas + return false; + } + public ServerStateNode removeRegionFromServer(final ServerName serverName, final RegionStateNode regionNode) { ServerStateNode serverNode = getOrCreateServer(serverName); 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 20b96efa1e7..114aee45f51 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 @@ -34,6 +34,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.function.Predicate; import java.util.stream.Collectors; + import org.apache.commons.lang3.NotImplementedException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.ClusterMetrics; @@ -51,15 +52,14 @@ import org.apache.hadoop.hbase.master.MasterServices; import org.apache.hadoop.hbase.master.RackManager; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.balancer.BaseLoadBalancer.Cluster.Action.Type; -import org.apache.yetus.audience.InterfaceAudience; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; import org.apache.hbase.thirdparty.com.google.common.base.Joiner; import org.apache.hbase.thirdparty.com.google.common.collect.ArrayListMultimap; import org.apache.hbase.thirdparty.com.google.common.collect.Lists; import org.apache.hbase.thirdparty.com.google.common.collect.Sets; +import org.apache.yetus.audience.InterfaceAudience; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The base class for load balancers. It provides the the functions used to by @@ -1454,8 +1454,13 @@ public abstract class BaseLoadBalancer implements LoadBalancer { for (Map.Entry entry : regions.entrySet()) { RegionInfo region = entry.getKey(); ServerName oldServerName = entry.getValue(); - if (!hasRegionReplica && !RegionReplicaUtil.isDefaultReplica(region)) { - hasRegionReplica = true; + // In the current set of regions even if one has region replica let us go with + // getting the entire snapshot + if (this.services != null && this.services.getAssignmentManager() != null) { // for tests + if (!hasRegionReplica && this.services.getAssignmentManager().getRegionStates() + .isReplicaAvailableForRegion(region)) { + hasRegionReplica = true; + } } List localServers = new ArrayList<>(); if (oldServerName != null) {