From 51f61c1ae53b0a0f784be8e4305c3ef92925caed Mon Sep 17 00:00:00 2001 From: ukumawat Date: Thu, 30 Oct 2025 13:12:34 +0530 Subject: [PATCH 01/10] HBASE-28158 Decouple RIT list management from TRSP --- .../hbase/rsgroup/RSGroupAdminServer.java | 17 ++- .../rsgroup/TestRSGroupsOfflineMode.java | 2 +- .../apache/hadoop/hbase/master/HMaster.java | 29 ++--- .../master/assignment/AssignmentManager.java | 89 +++++++++++-- .../assignment/AssignmentManagerUtil.java | 8 +- .../assignment/RegionInTransitionTracker.java | 121 ++++++++++++++++++ .../master/assignment/RegionStateNode.java | 13 +- .../hbase/master/assignment/RegionStates.java | 93 ++------------ .../procedure/FlushRegionProcedure.java | 2 +- .../master/procedure/ProcedureSyncWait.java | 7 +- .../ReopenTableRegionsProcedure.java | 2 +- .../procedure/ServerCrashProcedure.java | 2 + .../master/assignmentManagerStatus.jsp | 2 +- .../hadoop/hbase/HBaseTestingUtility.java | 49 ++++++- .../hbase/client/TestAsyncRegionAdminApi.java | 4 +- .../hbase/client/TestSplitOrMergeStatus.java | 4 +- .../master/TestAssignmentManagerMetrics.java | 2 +- .../master/TestMasterBalanceThrottling.java | 8 +- .../master/TestMasterDryRunBalancer.java | 2 +- .../assignment/AssignmentTestingUtil.java | 4 +- .../master/assignment/MockMasterServices.java | 2 +- .../assignment/TestAssignmentManagerBase.java | 2 +- .../assignment/TestAssignmentManagerUtil.java | 2 +- .../TestTransitRegionStateProcedure.java | 6 +- .../TestFavoredStochasticLoadBalancer.java | 11 +- .../master/http/TestMasterStatusUtil.java | 2 +- .../regionserver/TestHRegionFileSystem.java | 6 +- .../TestRegionMergeTransactionOnCluster.java | 17 +-- .../TestSplitTransactionOnCluster.java | 8 +- 29 files changed, 341 insertions(+), 175 deletions(-) create mode 100644 hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionInTransitionTracker.java diff --git a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java index 9d1b03e18eba..37b78aed80a7 100644 --- a/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java +++ b/hbase-rsgroup/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServer.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.SortedSet; import java.util.concurrent.Future; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -533,7 +534,7 @@ public BalanceResponse balanceRSGroup(String groupName, BalanceRequest request) if (groupRIT.size() > 0 && !request.isIgnoreRegionsInTransition()) { LOG.debug("Not running balancer because {} region(s) in transition: {}", groupRIT.size(), StringUtils.abbreviate( - master.getAssignmentManager().getRegionStates().getRegionsInTransition().toString(), + master.getAssignmentManager().getRegionsInTransition().toString(), 256)); return responseBuilder.build(); } @@ -654,19 +655,17 @@ public void updateConfiguration(String groupName) throws IOException { private Map rsGroupGetRegionsInTransition(String groupName) throws IOException { + SortedSet tablesInGroup = getRSGroupInfo(groupName).getTables(); Map rit = Maps.newTreeMap(); - AssignmentManager am = master.getAssignmentManager(); - for (TableName tableName : getRSGroupInfo(groupName).getTables()) { - for (RegionInfo regionInfo : am.getRegionStates().getRegionsOfTable(tableName)) { - RegionState state = am.getRegionStates().getRegionTransitionState(regionInfo); - if (state != null) { - rit.put(regionInfo.getEncodedName(), state); - } + for (RegionStateNode regionNode : master.getAssignmentManager() + .getRegionsInTransition()) { + TableName tn = regionNode.getTable(); + if (tablesInGroup.contains(tn)) { + rit.put(regionNode.getRegionInfo().getEncodedName(), regionNode.toRegionState()); } } return rit; } - /** * This is an EXPENSIVE clone. Cloning though is the safest thing to do. Can't let out original * since it can change and at least the load balancer wants to iterate this exported list. Load diff --git a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java index 452fd63d3c88..0d1810101a38 100644 --- a/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java +++ b/hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsOfflineMode.java @@ -138,7 +138,7 @@ public boolean evaluate() throws Exception { @Override public boolean evaluate() throws Exception { return groupRS.getNumberOfOnlineRegions() < 1 - && master.getAssignmentManager().getRegionStates().getRegionsInTransitionCount() < 1; + && master.getAssignmentManager().getRegionsInTransitionCount() < 1; } }); // Move table to group and wait. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java index 35f212b44597..bba1a1df1ab2 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -1001,6 +1001,13 @@ private void finishActiveMasterInitialization() throws IOException, InterruptedE Map, List>> procsByType = procedureExecutor .getActiveProceduresNoCopy().stream().collect(Collectors.groupingBy(p -> p.getClass())); + // This manager will be started AFTER hbase:meta is confirmed on line. + // hbase.mirror.table.state.to.zookeeper is so hbase1 clients can connect. They read table + // state from zookeeper while hbase2 reads it from hbase:meta. Disable if no hbase1 clients. + this.tableStateManager = + this.conf.getBoolean(MirroringTableStateManager.MIRROR_TABLE_STATE_TO_ZK_KEY, true) + ? new MirroringTableStateManager(this) + : new TableStateManager(this); // Create Assignment Manager this.assignmentManager = createAssignmentManager(this, masterRegion); this.assignmentManager.start(); @@ -1023,13 +1030,6 @@ private void finishActiveMasterInitialization() throws IOException, InterruptedE .map(p -> (ServerCrashProcedure) p).map(p -> p.getServerName()).collect(Collectors.toSet()), Sets.union(rsListStorage.getAll(), walManager.getLiveServersFromWALDir()), walManager.getSplittingServersFromWALDir()); - // This manager will be started AFTER hbase:meta is confirmed on line. - // hbase.mirror.table.state.to.zookeeper is so hbase1 clients can connect. They read table - // state from zookeeper while hbase2 reads it from hbase:meta. Disable if no hbase1 clients. - this.tableStateManager = - this.conf.getBoolean(MirroringTableStateManager.MIRROR_TABLE_STATE_TO_ZK_KEY, true) - ? new MirroringTableStateManager(this) - : new TableStateManager(this); startupTaskGroup.addTask("Initializing ZK system trackers"); initializeZKBasedSystemTrackers(); @@ -1944,7 +1944,7 @@ private void balanceThrottling(long nextBalanceStartTime, int maxRegionsInTransi // But if there are zero regions in transition, it can skip sleep to speed up. while ( !interrupted && EnvironmentEdgeManager.currentTime() < nextBalanceStartTime - && this.assignmentManager.getRegionStates().hasRegionsInTransition() + && this.assignmentManager.getRegionTransitScheduledCount() > 0 ) { try { Thread.sleep(100); @@ -1956,8 +1956,7 @@ private void balanceThrottling(long nextBalanceStartTime, int maxRegionsInTransi // Throttling by max number regions in transition while ( !interrupted && maxRegionsInTransition > 0 - && this.assignmentManager.getRegionStates().getRegionsInTransitionCount() - >= maxRegionsInTransition + && this.assignmentManager.getRegionTransitScheduledCount() >= maxRegionsInTransition && EnvironmentEdgeManager.currentTime() <= cutoffTime ) { try { @@ -2036,7 +2035,7 @@ public BalanceResponse balance(BalanceRequest request) throws IOException { synchronized (this.balancer) { // Only allow one balance run at at time. - if (this.assignmentManager.hasRegionsInTransition()) { + if (this.assignmentManager.getRegionTransitScheduledCount() > 0) { List regionsInTransition = assignmentManager.getRegionsInTransition(); // if hbase:meta region is in transition, result of assignment cannot be recorded // ignore the force flag in that case @@ -2051,8 +2050,8 @@ public BalanceResponse balance(BalanceRequest request) throws IOException { if (!request.isIgnoreRegionsInTransition() || metaInTransition) { LOG.info("Not running balancer (ignoreRIT=false" + ", metaRIT=" + metaInTransition - + ") because " + regionsInTransition.size() + " region(s) in transition: " + toPrint - + (truncated ? "(truncated list)" : "")); + + ") because " + assignmentManager.getRegionTransitScheduledCount() + + " region(s) in transition: " + toPrint + (truncated ? "(truncated list)" : "")); return responseBuilder.build(); } } @@ -2188,7 +2187,7 @@ public boolean normalizeRegions(final NormalizeTableFilterParams ntfp, if (skipRegionManagementAction("region normalizer")) { return false; } - if (assignmentManager.hasRegionsInTransition()) { + if (assignmentManager.getRegionTransitScheduledCount() > 0) { return false; } @@ -3012,7 +3011,7 @@ public ClusterMetrics getClusterMetricsWithoutCoprocessor(EnumSet