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;

Reply via email to