This is an automated email from the ASF dual-hosted git repository. rmdmattingly pushed a commit to branch HBASE-30348-branch-2 in repository https://gitbox.apache.org/repos/asf/hbase.git
commit 130ab48dee8e6bc21b968e5df55503c6b833151f Author: Ray Mattingly <[email protected]> AuthorDate: Mon Aug 31 09:10:18 2026 -0400 HBASE-30348 Throttles should work for system tables (excluding quotas, meta) (#8585) Signed-off-by: Charles Connell <[email protected]> --- .../org/apache/hadoop/hbase/quotas/QuotaCache.java | 2 +- .../org/apache/hadoop/hbase/quotas/QuotaUtil.java | 14 +++++ .../hbase/quotas/RegionServerRpcQuotaManager.java | 2 +- .../apache/hadoop/hbase/quotas/TestQuotaUtil.java | 65 ++++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaCache.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaCache.java index 34104752e81..2b8c81a415f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaCache.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaCache.java @@ -155,7 +155,7 @@ public class QuotaCache implements Stoppable { * @return the limiter associated to the specified user/table */ public QuotaLimiter getUserLimiter(final UserGroupInformation ugi, final TableName table) { - if (table.isSystemTable()) { + if (QuotaUtil.isThrottleExempt(table)) { return NoopQuotaLimiter.get(); } return getUserQuotaState(ugi).getTableLimiter(table); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java index f7df09801e0..f32c9d10443 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/QuotaUtil.java @@ -647,6 +647,20 @@ public class QuotaUtil extends QuotaTableUtil { * @param conn connection to re-use * @param tableName table name which has moved into space quota violation */ + /** + * Returns true if the given table must never be subject to RPC throttling. + * <p> + * Only {@code hbase:meta} and {@code hbase:quota} are exempt. Throttling either of those risks + * deadlock, because the throttling machinery itself depends on them: quotas are loaded from + * {@code hbase:quota}, and clients resolve region locations through {@code hbase:meta}, so + * delaying those requests could prevent a throttle from ever being lifted. Every other table may + * be throttled, including the remaining tables in the {@code hbase} namespace and the backup + * tables. + */ + public static boolean isThrottleExempt(final TableName tableName) { + return TableName.META_TABLE_NAME.equals(tableName) || QUOTA_TABLE_NAME.equals(tableName); + } + public static void disableTableIfNotDisabled(Connection conn, TableName tableName) throws IOException { try { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RegionServerRpcQuotaManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RegionServerRpcQuotaManager.java index 34fc57cb081..a7167c3821a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RegionServerRpcQuotaManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RegionServerRpcQuotaManager.java @@ -137,7 +137,7 @@ public class RegionServerRpcQuotaManager implements RpcQuotaManager, Configurati */ public OperationQuota getQuota(final UserGroupInformation ugi, final TableName table, final int blockSizeBytes) { - if (isQuotaEnabled() && !table.isSystemTable() && isRpcThrottleEnabled()) { + if (isQuotaEnabled() && !QuotaUtil.isThrottleExempt(table) && isRpcThrottleEnabled()) { UserQuotaState userQuotaState = quotaCache.getUserQuotaState(ugi); QuotaLimiter userLimiter = userQuotaState.getTableLimiter(table); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaUtil.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaUtil.java new file mode 100644 index 00000000000..176f77d58ae --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaUtil.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.quotas; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.testclassification.RegionServerTests; +import org.apache.hadoop.hbase.testclassification.SmallTests; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag(RegionServerTests.TAG) +@Tag(SmallTests.TAG) +public class TestQuotaUtil { + + @Test + public void testMetaTableIsThrottleExempt() { + assertTrue(QuotaUtil.isThrottleExempt(TableName.META_TABLE_NAME)); + } + + @Test + public void testQuotaTableIsThrottleExempt() { + assertTrue(QuotaUtil.isThrottleExempt(QuotaTableUtil.QUOTA_TABLE_NAME)); + } + + @Test + public void testBackupTablesAreNotThrottleExempt() { + // Backup tables live in a system namespace, so they were previously exempt. They can + // accumulate very large cells, which makes them a meaningful source of IO pressure, so + // operators need to be able to throttle them. + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("backup:system"))); + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("backup:system_bulk"))); + } + + @Test + public void testOtherSystemTablesAreNotThrottleExempt() { + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("hbase:namespace"))); + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("hbase:acl"))); + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("hbase:labels"))); + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("hbase:rsgroup"))); + } + + @Test + public void testUserTablesAreNotThrottleExempt() { + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("my_table"))); + assertFalse(QuotaUtil.isThrottleExempt(TableName.valueOf("my_ns:my_table"))); + } +}
