This is an automated email from the ASF dual-hosted git repository.
cconnell pushed a commit to branch branch-2.6
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/branch-2.6 by this push:
new 9dbd6962199 HBASE-29502: Skip meta cache in
RegionReplicaReplicationEndpoint when only one replica found (#7202)
9dbd6962199 is described below
commit 9dbd6962199abbae19d480ccca2b353cecf14de9
Author: Charles Connell <[email protected]>
AuthorDate: Thu Aug 28 07:26:58 2025 -0400
HBASE-29502: Skip meta cache in RegionReplicaReplicationEndpoint when only
one replica found (#7202)
Signed-off by: Wellington Ramos Chevreuil <[email protected]>
Signed-off by: Chandra Sekhar K <[email protected]>
Signed-off by: Nick Dimiduk <[email protected]>
---
.../RegionReplicaReplicationEndpoint.java | 13 ++-
.../TestRegionReplicaReplicationEndpoint.java | 100 +++++++++++++++++++++
2 files changed, 111 insertions(+), 2 deletions(-)
diff --git
a/hbase-server/src/main/java/org/apache/hadoop/hbase/replication/regionserver/RegionReplicaReplicationEndpoint.java
b/hbase-server/src/main/java/org/apache/hadoop/hbase/replication/regionserver/RegionReplicaReplicationEndpoint.java
index 754811ce0e0..7dbb4f008f8 100644
---
a/hbase-server/src/main/java/org/apache/hadoop/hbase/replication/regionserver/RegionReplicaReplicationEndpoint.java
+++
b/hbase-server/src/main/java/org/apache/hadoop/hbase/replication/regionserver/RegionReplicaReplicationEndpoint.java
@@ -427,6 +427,7 @@ public class RegionReplicaReplicationEndpoint extends
HBaseReplicationEndpoint {
// invalidate the cache and check from meta
RegionLocations locations = null;
boolean useCache = true;
+ int retries = 0;
while (true) {
// get the replicas of the primary region
try {
@@ -439,12 +440,13 @@ public class RegionReplicaReplicationEndpoint extends
HBaseReplicationEndpoint {
// Replicas can take a while to come online. The cache may have only
the primary. If we
// keep going to the cache, we will not learn of the replicas and
their locations after
// they come online.
- if (useCache && locations.size() == 1 &&
TableName.isMetaTableName(tableName)) {
- if (tableDescriptors.get(tableName).getRegionReplication() > 1) {
+ if (useCache && locations.size() == 1) {
+ if (tableDescriptors.get(tableName).getRegionReplication() > 1 &&
retries <= 3) {
// Make an obnoxious log here. See how bad this issue is. Add a
timer if happening
// too much.
LOG.info("Skipping location cache; only one location found for
{}", tableName);
useCache = false;
+ retries++;
continue;
}
}
@@ -488,6 +490,13 @@ public class RegionReplicaReplicationEndpoint extends
HBaseReplicationEndpoint {
}
if (locations.size() == 1) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Skipping {} entries in table {} because only one region
location was found",
+ entries.size(), tableName);
+ for (Entry entry : entries) {
+ LOG.trace("Skipping: {}", entry);
+ }
+ }
return;
}
diff --git
a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestRegionReplicaReplicationEndpoint.java
b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestRegionReplicaReplicationEndpoint.java
index 9a03536f754..ffca0caabef 100644
---
a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestRegionReplicaReplicationEndpoint.java
+++
b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestRegionReplicaReplicationEndpoint.java
@@ -507,6 +507,106 @@ public class TestRegionReplicaReplicationEndpoint {
}
}
+ @Test
+ public void testMetaCacheMissTriggersRefresh() throws Exception {
+ TableName tableName = TableName.valueOf(name.getMethodName());
+ int regionReplication = 3;
+ HTableDescriptor htd = HTU.createTableDescriptor(tableName);
+ htd.setRegionReplication(regionReplication);
+ createOrEnableTableWithRetries(htd, true);
+
+ Connection connection =
ConnectionFactory.createConnection(HTU.getConfiguration());
+ Table table = connection.getTable(tableName);
+
+ try {
+ HTU.loadNumericRows(table, HBaseTestingUtility.fam1, 0, 100);
+
+ RegionLocator rl = connection.getRegionLocator(tableName);
+ HRegionLocation hrl = rl.getRegionLocation(HConstants.EMPTY_BYTE_ARRAY);
+ byte[] encodedRegionName = hrl.getRegionInfo().getEncodedNameAsBytes();
+ rl.close();
+
+ AtomicLong skippedEdits = new AtomicLong();
+ RegionReplicaReplicationEndpoint.RegionReplicaOutputSink sink =
+ mock(RegionReplicaReplicationEndpoint.RegionReplicaOutputSink.class);
+ when(sink.getSkippedEditsCounter()).thenReturn(skippedEdits);
+
+ FSTableDescriptors fstd =
+ new FSTableDescriptors(FileSystem.get(HTU.getConfiguration()),
HTU.getDefaultRootDirPath());
+
+ RegionReplicaReplicationEndpoint.RegionReplicaSinkWriter sinkWriter =
+ new RegionReplicaReplicationEndpoint.RegionReplicaSinkWriter(sink,
+ (ClusterConnection) connection, Executors.newSingleThreadExecutor(),
Integer.MAX_VALUE,
+ fstd);
+
+ Cell cell = CellBuilderFactory.create(CellBuilderType.DEEP_COPY)
+ .setRow(Bytes.toBytes("testRow")).setFamily(HBaseTestingUtility.fam1)
+ .setValue(Bytes.toBytes("testValue")).setType(Type.Put).build();
+
+ Entry entry =
+ new Entry(new WALKeyImpl(encodedRegionName, tableName, 1), new
WALEdit().add(cell));
+
+ sinkWriter.append(tableName, encodedRegionName, Bytes.toBytes("testRow"),
+ Lists.newArrayList(entry));
+
+ assertEquals("No entries should be skipped for valid table", 0,
skippedEdits.get());
+
+ } finally {
+ table.close();
+ connection.close();
+ }
+ }
+
+ @Test
+ public void testMetaCacheSkippedForSingleReplicaTable() throws Exception {
+ TableName tableName = TableName.valueOf(name.getMethodName());
+ int regionReplication = 1;
+ HTableDescriptor htd = HTU.createTableDescriptor(tableName);
+ htd.setRegionReplication(regionReplication);
+ createOrEnableTableWithRetries(htd, true);
+
+ Connection connection =
ConnectionFactory.createConnection(HTU.getConfiguration());
+ Table table = connection.getTable(tableName);
+
+ try {
+ HTU.loadNumericRows(table, HBaseTestingUtility.fam1, 0, 100);
+
+ RegionLocator rl = connection.getRegionLocator(tableName);
+ HRegionLocation hrl = rl.getRegionLocation(HConstants.EMPTY_BYTE_ARRAY);
+ byte[] encodedRegionName = hrl.getRegionInfo().getEncodedNameAsBytes();
+ rl.close();
+
+ AtomicLong skippedEdits = new AtomicLong();
+ RegionReplicaReplicationEndpoint.RegionReplicaOutputSink sink =
+ mock(RegionReplicaReplicationEndpoint.RegionReplicaOutputSink.class);
+ when(sink.getSkippedEditsCounter()).thenReturn(skippedEdits);
+
+ FSTableDescriptors fstd =
+ new FSTableDescriptors(FileSystem.get(HTU.getConfiguration()),
HTU.getDefaultRootDirPath());
+
+ RegionReplicaReplicationEndpoint.RegionReplicaSinkWriter sinkWriter =
+ new RegionReplicaReplicationEndpoint.RegionReplicaSinkWriter(sink,
+ (ClusterConnection) connection, Executors.newSingleThreadExecutor(),
Integer.MAX_VALUE,
+ fstd);
+
+ Cell cell = CellBuilderFactory.create(CellBuilderType.DEEP_COPY)
+ .setRow(Bytes.toBytes("testRow")).setFamily(HBaseTestingUtility.fam1)
+ .setValue(Bytes.toBytes("testValue")).setType(Type.Put).build();
+
+ Entry entry =
+ new Entry(new WALKeyImpl(encodedRegionName, tableName, 1), new
WALEdit().add(cell));
+
+ sinkWriter.append(tableName, encodedRegionName, Bytes.toBytes("testRow"),
+ Lists.newArrayList(entry));
+
+ assertEquals("No entries should be skipped for single replica table", 0,
skippedEdits.get());
+
+ } finally {
+ table.close();
+ connection.close();
+ }
+ }
+
private void createOrEnableTableWithRetries(TableDescriptor htd, boolean
createTableOperation) {
// Helper function to run create/enable table operations with a retry
feature
boolean continueToRetry = true;