This is an automated email from the ASF dual-hosted git repository. rmattingly pushed a commit to branch HBASE-29075-branch-2 in repository https://gitbox.apache.org/repos/asf/hbase.git
commit 1b7179b42068842076da09d47e06ccd6966ee99b Author: Ray Mattingly <[email protected]> AuthorDate: Thu Mar 6 08:25:44 2025 -0500 HBASE-29075 Balancer conditionals should support system table isolation (#6746) Co-authored-by: Ray Mattingly <[email protected]> Signed-off-by: Nick Dimiduk <[email protected]> --- .../master/balancer/BalancerConditionals.java | 14 +++++ .../balancer/DistributeReplicasConditional.java | 6 +- .../balancer/MetaTableIsolationConditional.java | 3 +- .../balancer/SlopFixingCandidateGenerator.java | 5 +- ...=> SystemTableIsolationCandidateGenerator.java} | 24 ++++---- ...l.java => SystemTableIsolationConditional.java} | 22 +++++--- .../master/balancer/TableIsolationConditional.java | 9 +-- .../balancer/CandidateGeneratorTestUtil.java | 9 ++- ...LargeClusterBalancingSystemTableIsolation.java} | 66 ++++++++-------------- ...ancingTableIsolationAndReplicaDistribution.java | 28 +++++---- 10 files changed, 100 insertions(+), 86 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BalancerConditionals.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BalancerConditionals.java index 88ceb5a5540..021a34bce6b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BalancerConditionals.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/BalancerConditionals.java @@ -62,6 +62,10 @@ final class BalancerConditionals implements Configurable { "hbase.master.balancer.stochastic.conditionals.isolateMetaTable"; public static final boolean ISOLATE_META_TABLE_DEFAULT = false; + public static final String ISOLATE_SYSTEM_TABLES_KEY = + "hbase.master.balancer.stochastic.conditionals.isolateSystemTables"; + public static final boolean ISOLATE_SYSTEM_TABLES_DEFAULT = false; + public static final String ADDITIONAL_CONDITIONALS_KEY = "hbase.master.balancer.stochastic.additionalConditionals"; @@ -96,6 +100,10 @@ final class BalancerConditionals implements Configurable { } boolean isTableIsolationEnabled() { + return conditionalClasses.stream().anyMatch(TableIsolationConditional.class::isAssignableFrom); + } + + boolean isMetaTableIsolationEnabled() { return conditionalClasses.contains(MetaTableIsolationConditional.class); } @@ -208,6 +216,12 @@ final class BalancerConditionals implements Configurable { conditionalClasses.add(MetaTableIsolationConditional.class); } + boolean isolateSystemTables = + conf.getBoolean(ISOLATE_SYSTEM_TABLES_KEY, ISOLATE_SYSTEM_TABLES_DEFAULT); + if (isolateSystemTables) { + conditionalClasses.add(SystemTableIsolationConditional.class); + } + Class<?>[] classes = conf.getClasses(ADDITIONAL_CONDITIONALS_KEY); for (Class<?> clazz : classes) { if (!RegionPlanConditional.class.isAssignableFrom(clazz)) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/DistributeReplicasConditional.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/DistributeReplicasConditional.java index 2cd27615e5f..e99c0e93a15 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/DistributeReplicasConditional.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/DistributeReplicasConditional.java @@ -19,7 +19,6 @@ package org.apache.hadoop.hbase.master.balancer; import java.util.List; import java.util.Set; -import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.master.RegionPlan; import org.apache.hadoop.hbase.master.balancer.replicas.ReplicaKey; @@ -41,12 +40,9 @@ public class DistributeReplicasConditional extends RegionPlanConditional { public DistributeReplicasConditional(BalancerConditionals balancerConditionals, BalancerClusterState cluster) { super(balancerConditionals.getConf(), cluster); - Configuration conf = balancerConditionals.getConf(); - float slop = - conf.getFloat(BaseLoadBalancer.REGIONS_SLOP_KEY, BaseLoadBalancer.REGIONS_SLOP_DEFAULT); this.candidateGenerators = ImmutableList.of(new DistributeReplicasCandidateGenerator(balancerConditionals), - new SlopFixingCandidateGenerator(balancerConditionals, slop)); + new SlopFixingCandidateGenerator(balancerConditionals)); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java index 732693c44f3..5617468457c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java @@ -27,7 +27,8 @@ class MetaTableIsolationConditional extends TableIsolationConditional { public MetaTableIsolationConditional(BalancerConditionals balancerConditionals, BalancerClusterState cluster) { - super(balancerConditionals, cluster); + super(new MetaTableIsolationCandidateGenerator(balancerConditionals), balancerConditionals, + cluster); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SlopFixingCandidateGenerator.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SlopFixingCandidateGenerator.java index b1ea1de8d2b..f78e1573b41 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SlopFixingCandidateGenerator.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SlopFixingCandidateGenerator.java @@ -37,9 +37,10 @@ final class SlopFixingCandidateGenerator extends RegionPlanConditionalCandidateG private final float slop; - SlopFixingCandidateGenerator(BalancerConditionals balancerConditionals, float slop) { + SlopFixingCandidateGenerator(BalancerConditionals balancerConditionals) { super(balancerConditionals); - this.slop = slop; + this.slop = balancerConditionals.getConf().getFloat(BaseLoadBalancer.REGIONS_SLOP_KEY, + BaseLoadBalancer.REGIONS_SLOP_DEFAULT); } @Override diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SystemTableIsolationCandidateGenerator.java similarity index 57% copy from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java copy to hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SystemTableIsolationCandidateGenerator.java index 732693c44f3..7ce8ff20296 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SystemTableIsolationCandidateGenerator.java @@ -18,20 +18,24 @@ package org.apache.hadoop.hbase.master.balancer; import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.yetus.audience.InterfaceAudience; -/** - * If enabled, this class will help the balancer ensure that the meta table lives on its own - * RegionServer. Configure this via {@link BalancerConditionals#ISOLATE_META_TABLE_KEY} - */ -class MetaTableIsolationConditional extends TableIsolationConditional { [email protected] +public class SystemTableIsolationCandidateGenerator extends TableIsolationCandidateGenerator { + + private final BalancerConditionals balancerConditionals; - public MetaTableIsolationConditional(BalancerConditionals balancerConditionals, - BalancerClusterState cluster) { - super(balancerConditionals, cluster); + SystemTableIsolationCandidateGenerator(BalancerConditionals balancerConditionals) { + super(balancerConditionals); + this.balancerConditionals = balancerConditionals; } @Override - boolean isRegionToIsolate(RegionInfo regionInfo) { - return regionInfo.isMetaRegion(); + boolean shouldBeIsolated(RegionInfo regionInfo) { + if (balancerConditionals.isMetaTableIsolationEnabled() && regionInfo.isMetaRegion()) { + // If meta isolation is enabled, we can ignore meta regions here + return false; + } + return regionInfo.getTable().isSystemTable(); } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SystemTableIsolationConditional.java similarity index 59% copy from hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java copy to hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SystemTableIsolationConditional.java index 732693c44f3..b5734b82faf 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/MetaTableIsolationConditional.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/SystemTableIsolationConditional.java @@ -18,20 +18,26 @@ package org.apache.hadoop.hbase.master.balancer; import org.apache.hadoop.hbase.client.RegionInfo; +import org.apache.yetus.audience.InterfaceAudience; -/** - * If enabled, this class will help the balancer ensure that the meta table lives on its own - * RegionServer. Configure this via {@link BalancerConditionals#ISOLATE_META_TABLE_KEY} - */ -class MetaTableIsolationConditional extends TableIsolationConditional { [email protected] +public class SystemTableIsolationConditional extends TableIsolationConditional { + + private final BalancerConditionals balancerConditionals; - public MetaTableIsolationConditional(BalancerConditionals balancerConditionals, + SystemTableIsolationConditional(BalancerConditionals balancerConditionals, BalancerClusterState cluster) { - super(balancerConditionals, cluster); + super(new SystemTableIsolationCandidateGenerator(balancerConditionals), balancerConditionals, + cluster); + this.balancerConditionals = balancerConditionals; } @Override boolean isRegionToIsolate(RegionInfo regionInfo) { - return regionInfo.isMetaRegion(); + if (balancerConditionals.isMetaTableIsolationEnabled() && regionInfo.isMetaRegion()) { + // If meta isolation is enabled, we can ignore meta regions here + return false; + } + return regionInfo.getTable().isSystemTable(); } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/TableIsolationConditional.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/TableIsolationConditional.java index cd3ce0b6fe1..24a6f519e8d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/TableIsolationConditional.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/balancer/TableIsolationConditional.java @@ -28,15 +28,12 @@ abstract class TableIsolationConditional extends RegionPlanConditional { private final List<RegionPlanConditionalCandidateGenerator> candidateGenerators; - TableIsolationConditional(BalancerConditionals balancerConditionals, - BalancerClusterState cluster) { + TableIsolationConditional(TableIsolationCandidateGenerator generator, + BalancerConditionals balancerConditionals, BalancerClusterState cluster) { super(balancerConditionals.getConf(), cluster); - float slop = balancerConditionals.getConf().getFloat(BaseLoadBalancer.REGIONS_SLOP_KEY, - BaseLoadBalancer.REGIONS_SLOP_DEFAULT); this.candidateGenerators = - ImmutableList.of(new MetaTableIsolationCandidateGenerator(balancerConditionals), - new SlopFixingCandidateGenerator(balancerConditionals, slop)); + ImmutableList.of(generator, new SlopFixingCandidateGenerator(balancerConditionals)); } abstract boolean isRegionToIsolate(RegionInfo regionInfo); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/CandidateGeneratorTestUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/CandidateGeneratorTestUtil.java index d2a2d432ff0..03bfcce8e15 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/CandidateGeneratorTestUtil.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/CandidateGeneratorTestUtil.java @@ -54,9 +54,16 @@ public final class CandidateGeneratorTestUtil { static void runBalancerToExhaustion(Configuration conf, Map<ServerName, List<RegionInfo>> serverToRegions, Set<Function<BalancerClusterState, Boolean>> expectations, float targetMaxBalancerCost) { + runBalancerToExhaustion(conf, serverToRegions, expectations, targetMaxBalancerCost, 15000); + } + + static void runBalancerToExhaustion(Configuration conf, + Map<ServerName, List<RegionInfo>> serverToRegions, + Set<Function<BalancerClusterState, Boolean>> expectations, float targetMaxBalancerCost, + long maxRunningTime) { // Do the full plan. We're testing with a lot of regions conf.setBoolean("hbase.master.balancer.stochastic.runMaxSteps", true); - conf.setLong(MAX_RUNNING_TIME_KEY, 15000); + conf.setLong(MAX_RUNNING_TIME_KEY, maxRunningTime); conf.setFloat(MIN_COST_NEED_BALANCE_KEY, targetMaxBalancerCost); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingSystemTableIsolation.java similarity index 59% copy from hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java copy to hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingSystemTableIsolation.java index 5fbddf4878b..ef26c548c20 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingSystemTableIsolation.java @@ -42,20 +42,20 @@ import org.slf4j.LoggerFactory; import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableSet; @Category({ MediumTests.class, MasterTests.class }) -public class TestLargeClusterBalancingTableIsolationAndReplicaDistribution { +public class TestLargeClusterBalancingSystemTableIsolation { @ClassRule - public static final HBaseClassTestRule CLASS_RULE = HBaseClassTestRule - .forClass(TestLargeClusterBalancingTableIsolationAndReplicaDistribution.class); + public static final HBaseClassTestRule CLASS_RULE = + HBaseClassTestRule.forClass(TestLargeClusterBalancingSystemTableIsolation.class); private static final Logger LOG = - LoggerFactory.getLogger(TestLargeClusterBalancingTableIsolationAndReplicaDistribution.class); + LoggerFactory.getLogger(TestLargeClusterBalancingSystemTableIsolation.class); + private static final TableName SYSTEM_TABLE_NAME = TableName.valueOf("hbase:system"); - private static final TableName NON_ISOLATED_TABLE_NAME = TableName.valueOf("userTable"); + private static final TableName NON_SYSTEM_TABLE_NAME = TableName.valueOf("userTable"); private static final int NUM_SERVERS = 1000; - private static final int NUM_REGIONS = 10_000; - private static final int NUM_REPLICAS = 3; + private static final int NUM_REGIONS = 20_000; private static final ServerName[] servers = new ServerName[NUM_SERVERS]; private static final Map<ServerName, List<RegionInfo>> serverToRegions = new HashMap<>(); @@ -65,58 +65,40 @@ public class TestLargeClusterBalancingTableIsolationAndReplicaDistribution { // Initialize servers for (int i = 0; i < NUM_SERVERS; i++) { servers[i] = ServerName.valueOf("server" + i, i, System.currentTimeMillis()); - serverToRegions.put(servers[i], new ArrayList<>()); } - // Create primary regions and their replicas + // Create regions List<RegionInfo> allRegions = new ArrayList<>(); for (int i = 0; i < NUM_REGIONS; i++) { - TableName tableName; - if (i < 1) { - tableName = TableName.META_TABLE_NAME; - } else if (i < 10) { - tableName = SYSTEM_TABLE_NAME; - } else { - tableName = NON_ISOLATED_TABLE_NAME; - } - - // Define startKey and endKey for the region + TableName tableName = i < 3 ? SYSTEM_TABLE_NAME : NON_SYSTEM_TABLE_NAME; byte[] startKey = new byte[1]; startKey[0] = (byte) i; byte[] endKey = new byte[1]; endKey[0] = (byte) (i + 1); - // Create 3 replicas for each primary region - for (int replicaId = 0; replicaId < NUM_REPLICAS; replicaId++) { - RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tableName).setStartKey(startKey) - .setEndKey(endKey).setReplicaId(replicaId).build(); - allRegions.add(regionInfo); - } + RegionInfo regionInfo = + RegionInfoBuilder.newBuilder(tableName).setStartKey(startKey).setEndKey(endKey).build(); + allRegions.add(regionInfo); } - // Assign all regions to one server - for (RegionInfo regionInfo : allRegions) { - serverToRegions.get(servers[0]).add(regionInfo); + // Assign all regions to the first server + serverToRegions.put(servers[0], new ArrayList<>(allRegions)); + for (int i = 1; i < NUM_SERVERS; i++) { + serverToRegions.put(servers[i], new ArrayList<>()); } } @Test - public void testTableIsolationAndReplicaDistribution() { - + public void testSystemTableIsolation() { Configuration conf = new Configuration(false); - conf.setBoolean(BalancerConditionals.ISOLATE_META_TABLE_KEY, true); - DistributeReplicasTestConditional.enableConditionalReplicaDistributionForTest(conf); - - runBalancerToExhaustion(conf, serverToRegions, ImmutableSet.of(this::isMetaTableIsolated, - CandidateGeneratorTestUtil::areAllReplicasDistributed), 10.0f); - LOG.info("Meta table regions are successfully isolated, " - + "and region replicas are appropriately distributed."); + conf.setBoolean(BalancerConditionals.ISOLATE_SYSTEM_TABLES_KEY, true); + runBalancerToExhaustion(conf, serverToRegions, ImmutableSet.of(this::isSystemTableIsolated), + 10.0f); + LOG.info("Meta table regions are successfully isolated."); } - /** - * Validates whether all meta table regions are isolated. - */ - private boolean isMetaTableIsolated(BalancerClusterState cluster) { - return isTableIsolated(cluster, TableName.META_TABLE_NAME, "Meta"); + private boolean isSystemTableIsolated(BalancerClusterState cluster) { + return isTableIsolated(cluster, SYSTEM_TABLE_NAME, "System"); } + } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java index 5fbddf4878b..3a28ae801e4 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/balancer/TestLargeClusterBalancingTableIsolationAndReplicaDistribution.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.ServerName; @@ -53,8 +54,8 @@ public class TestLargeClusterBalancingTableIsolationAndReplicaDistribution { private static final TableName SYSTEM_TABLE_NAME = TableName.valueOf("hbase:system"); private static final TableName NON_ISOLATED_TABLE_NAME = TableName.valueOf("userTable"); - private static final int NUM_SERVERS = 1000; - private static final int NUM_REGIONS = 10_000; + private static final int NUM_SERVERS = 500; + private static final int NUM_REGIONS = 2_500; private static final int NUM_REPLICAS = 3; private static final ServerName[] servers = new ServerName[NUM_SERVERS]; @@ -69,7 +70,6 @@ public class TestLargeClusterBalancingTableIsolationAndReplicaDistribution { } // Create primary regions and their replicas - List<RegionInfo> allRegions = new ArrayList<>(); for (int i = 0; i < NUM_REGIONS; i++) { TableName tableName; if (i < 1) { @@ -86,29 +86,28 @@ public class TestLargeClusterBalancingTableIsolationAndReplicaDistribution { byte[] endKey = new byte[1]; endKey[0] = (byte) (i + 1); + Random random = new Random(); // Create 3 replicas for each primary region for (int replicaId = 0; replicaId < NUM_REPLICAS; replicaId++) { RegionInfo regionInfo = RegionInfoBuilder.newBuilder(tableName).setStartKey(startKey) .setEndKey(endKey).setReplicaId(replicaId).build(); - allRegions.add(regionInfo); + // Assign region to random server + int randomServer = random.nextInt(servers.length); + serverToRegions.get(servers[randomServer]).add(regionInfo); } } - - // Assign all regions to one server - for (RegionInfo regionInfo : allRegions) { - serverToRegions.get(servers[0]).add(regionInfo); - } } @Test public void testTableIsolationAndReplicaDistribution() { - Configuration conf = new Configuration(false); conf.setBoolean(BalancerConditionals.ISOLATE_META_TABLE_KEY, true); + conf.setBoolean(BalancerConditionals.ISOLATE_SYSTEM_TABLES_KEY, true); DistributeReplicasTestConditional.enableConditionalReplicaDistributionForTest(conf); runBalancerToExhaustion(conf, serverToRegions, ImmutableSet.of(this::isMetaTableIsolated, - CandidateGeneratorTestUtil::areAllReplicasDistributed), 10.0f); + this::isSystemTableIsolated, CandidateGeneratorTestUtil::areAllReplicasDistributed), 10.0f, + 60_000); LOG.info("Meta table regions are successfully isolated, " + "and region replicas are appropriately distributed."); } @@ -119,4 +118,11 @@ public class TestLargeClusterBalancingTableIsolationAndReplicaDistribution { private boolean isMetaTableIsolated(BalancerClusterState cluster) { return isTableIsolated(cluster, TableName.META_TABLE_NAME, "Meta"); } + + /** + * Validates whether all meta table regions are isolated. + */ + private boolean isSystemTableIsolated(BalancerClusterState cluster) { + return isTableIsolated(cluster, SYSTEM_TABLE_NAME, "System"); + } }
