You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2021/07/22 15:48:42 UTC

[hbase] 07/09: HBASE-24607 Implement CatalogJanitor for 'root table' (#2377)

This is an automated email from the ASF dual-hosted git repository.

zhangduo pushed a commit to branch HBASE-24950
in repository https://gitbox.apache.org/repos/asf/hbase.git

commit 75949d509898b3f008dd931a6486acd4d2e425c4
Author: Duo Zhang <zh...@apache.org>
AuthorDate: Fri Sep 11 13:31:00 2020 +0800

    HBASE-24607 Implement CatalogJanitor for 'root table' (#2377)
    
    Signed-off-by: Guanghao Zhang <zg...@apache.org>
---
 .../hadoop/hbase/ClientMetaTableAccessor.java      |  7 --
 .../org/apache/hadoop/hbase/MetaTableAccessor.java | 10 ---
 .../hbase/master/assignment/GCRegionProcedure.java |  8 +--
 .../hbase/master/assignment/RegionStateStore.java  | 78 ++++++++++++++++++----
 .../hbase/master/janitor/CatalogJanitor.java       |  4 +-
 .../hbase/master/janitor/ReportMakingVisitor.java  | 15 ++---
 .../hadoop/hbase/TestSimpleMetaSplitMerge.java     | 42 +++++++++---
 7 files changed, 103 insertions(+), 61 deletions(-)

diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java
index 74d2322..ed0d9b4 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ClientMetaTableAccessor.java
@@ -19,7 +19,6 @@ package org.apache.hadoop.hbase;
 
 import static org.apache.hadoop.hbase.util.FutureUtils.addListener;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -334,12 +333,6 @@ public final class ClientMetaTableAccessor {
   }
 
   /**
-   * Implementations 'visit' a catalog table row but with close() at the end.
-   */
-  public interface CloseableVisitor extends Visitor, Closeable {
-  }
-
-  /**
    * A {@link Visitor} that collects content out of passed {@link Result}.
    */
   private static abstract class CollectingVisitor<T> implements Visitor {
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
index 512916f..385f2b9 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/MetaTableAccessor.java
@@ -19,7 +19,6 @@ package org.apache.hadoop.hbase;
 
 import edu.umd.cs.findbugs.annotations.NonNull;
 import edu.umd.cs.findbugs.annotations.Nullable;
-import java.io.Closeable;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -49,7 +48,6 @@ import org.apache.hadoop.hbase.filter.SubstringComparator;
 import org.apache.hadoop.hbase.master.RegionState;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
-import org.apache.hadoop.hbase.util.ExceptionUtil;
 import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.hbase.util.PairOfSameType;
 import org.apache.yetus.audience.InterfaceAudience;
@@ -504,14 +502,6 @@ public final class MetaTableAccessor {
         }
       }
     }
-    if (visitor instanceof Closeable) {
-      try {
-        ((Closeable) visitor).close();
-      } catch (Throwable t) {
-        ExceptionUtil.rethrowIfInterrupt(t);
-        LOG.debug("Got exception in closing the meta scanner visitor", t);
-      }
-    }
   }
 
   /**
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/GCRegionProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/GCRegionProcedure.java
index dfd2314..e21e51d 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/GCRegionProcedure.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/GCRegionProcedure.java
@@ -109,12 +109,8 @@ public class GCRegionProcedure extends AbstractStateMachineRegionProcedure<GCReg
           // TODO: Purge metadata before removing from HDFS? This ordering is copied
           // from CatalogJanitor.
           AssignmentManager am = masterServices.getAssignmentManager();
-          if (am != null) {
-            if (am.getRegionStates() != null) {
-              am.getRegionStates().deleteRegion(getRegion());
-            }
-          }
-          env.getAssignmentManager().getRegionStateStore().deleteRegion(getRegion());
+          am.getRegionStates().deleteRegion(getRegion());
+          am.getRegionStateStore().deleteRegion(getRegion());
           masterServices.getServerManager().removeRegion(getRegion());
           FavoredNodesManager fnm = masterServices.getFavoredNodesManager();
           if (fnm != null) {
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
index 98e6f2e..2ffd232 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/assignment/RegionStateStore.java
@@ -66,8 +66,6 @@ import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.FutureUtils;
 import org.apache.hadoop.hbase.wal.WALSplitUtil;
 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
-import org.apache.hadoop.hbase.zookeeper.ZKUtil;
-import org.apache.hadoop.hbase.zookeeper.ZKWatcher;
 import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.zookeeper.KeeperException;
 import org.slf4j.Logger;
@@ -227,6 +225,28 @@ public class RegionStateStore {
     }
   }
 
+  public void scanCatalog(ClientMetaTableAccessor.Visitor visitor) throws IOException {
+    // scan meta first
+    MetaTableAccessor.fullScanRegions(master.getConnection(), visitor);
+    // scan root
+    try (RegionScanner scanner =
+      masterRegion.getScanner(new Scan().addFamily(HConstants.CATALOG_FAMILY))) {
+      boolean moreRows;
+      List<Cell> cells = new ArrayList<>();
+      do {
+        moreRows = scanner.next(cells);
+        if (cells.isEmpty()) {
+          continue;
+        }
+        Result result = Result.create(cells);
+        cells.clear();
+        if (!visitor.visit(result)) {
+          break;
+        }
+      } while (moreRows);
+    }
+  }
+
   public void mirrorMetaLocation(RegionInfo regionInfo, ServerName serverName, State state)
     throws IOException {
     try {
@@ -454,7 +474,7 @@ public class RegionStateStore {
     if (cells == null || cells.length == 0) {
       return;
     }
-    Delete delete = new Delete(mergeRegion.getRegionName());
+    Delete delete = new Delete(CatalogFamilyFormat.getMetaKeyForRegion(mergeRegion));
     List<byte[]> qualifiers = new ArrayList<>();
     for (Cell cell : cells) {
       if (!CatalogFamilyFormat.isMergeQualifierPrefix(cell)) {
@@ -473,8 +493,13 @@ public class RegionStateStore {
         " in meta table, they are cleaned up already, Skip.");
       return;
     }
-    try (Table table = master.getConnection().getTable(TableName.META_TABLE_NAME)) {
-      table.delete(delete);
+    debugLogMutation(delete);
+    if (mergeRegion.isMetaRegion()) {
+      masterRegion.update(r -> r.delete(delete));
+    } else {
+      try (Table table = getMetaTable()) {
+        table.delete(delete);
+      }
     }
     LOG.info("Deleted merge references in " + mergeRegion.getRegionNameAsString() +
       ", deleted qualifiers " +
@@ -517,19 +542,44 @@ public class RegionStateStore {
     deleteRegions(regions, EnvironmentEdgeManager.currentTime());
   }
 
+  private static Delete makeDeleteRegionInfo(RegionInfo regionInfo, long ts) {
+    return new Delete(CatalogFamilyFormat.getMetaKeyForRegion(regionInfo))
+      .addFamily(HConstants.CATALOG_FAMILY, ts);
+  }
+
+  private static List<Delete> makeDeleteRegionInfos(List<RegionInfo> regionInfos, long ts) {
+    return regionInfos.stream().map(ri -> makeDeleteRegionInfo(ri, ts))
+      .collect(Collectors.toList());
+  }
+
   private void deleteRegions(List<RegionInfo> regions, long ts) throws IOException {
-    List<Delete> deletes = new ArrayList<>(regions.size());
-    for (RegionInfo hri : regions) {
-      Delete e = new Delete(hri.getRegionName());
-      e.addFamily(HConstants.CATALOG_FAMILY, ts);
-      deletes.add(e);
+    List<RegionInfo> metaRegions = new ArrayList<>();
+    List<RegionInfo> nonMetaRegions = new ArrayList<>();
+    for (RegionInfo region : regions) {
+      if (region.isMetaRegion()) {
+        metaRegions.add(region);
+      } else {
+        nonMetaRegions.add(region);
+      }
     }
-    try (Table table = getMetaTable()) {
+    if (!metaRegions.isEmpty()) {
+      List<Delete> deletes = makeDeleteRegionInfos(metaRegions, ts);
       debugLogMutations(deletes);
-      table.delete(deletes);
+      for (Delete d : deletes) {
+        masterRegion.update(r -> r.delete(d));
+      }
+      LOG.info("Deleted {} regions from ROOT", metaRegions.size());
+      LOG.debug("Deleted regions: {}", metaRegions);
+    }
+    if (!nonMetaRegions.isEmpty()) {
+      List<Delete> deletes = makeDeleteRegionInfos(nonMetaRegions, ts);
+      debugLogMutations(deletes);
+      try (Table table = getMetaTable()) {
+        table.delete(deletes);
+      }
+      LOG.info("Deleted {} regions from META", nonMetaRegions.size());
+      LOG.debug("Deleted regions: {}", nonMetaRegions);
     }
-    LOG.info("Deleted {} regions from META", regions.size());
-    LOG.debug("Deleted regions: {}", regions);
   }
 
   /**
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.java
index fee218e..b01e07d 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.java
@@ -231,8 +231,8 @@ public class CatalogJanitor extends ScheduledChore {
   // will be override in tests.
   protected Report scanForReport() throws IOException {
     ReportMakingVisitor visitor = new ReportMakingVisitor(this.services);
-    // Null tablename means scan all of meta.
-    MetaTableAccessor.scanMetaForTableRegions(this.services.getConnection(), visitor, null);
+    services.getAssignmentManager().getRegionStateStore().scanCatalog(visitor);
+    visitor.done();
     return visitor.getReport();
   }
 
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/ReportMakingVisitor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/ReportMakingVisitor.java
index 4dd514e..77188de 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/ReportMakingVisitor.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/janitor/ReportMakingVisitor.java
@@ -44,7 +44,7 @@ import org.slf4j.LoggerFactory;
  * {@link #close()}'d.
  */
 @InterfaceAudience.Private
-class ReportMakingVisitor implements ClientMetaTableAccessor.CloseableVisitor {
+class ReportMakingVisitor implements ClientMetaTableAccessor.Visitor {
 
   private static final Logger LOG = LoggerFactory.getLogger(ReportMakingVisitor.class);
 
@@ -199,14 +199,8 @@ class ReportMakingVisitor implements ClientMetaTableAccessor.CloseableVisitor {
   /**
    * @return True if table is disabled or disabling; defaults false!
    */
-  boolean isTableDisabled(RegionInfo ri) {
-    if (ri == null) {
-      return false;
-    }
-    if (this.services == null) {
-      return false;
-    }
-    if (this.services.getTableStateManager() == null) {
+  private boolean isTableDisabled(RegionInfo ri) {
+    if (ri.isMetaRegion()) {
       return false;
     }
     TableState state = null;
@@ -282,8 +276,7 @@ class ReportMakingVisitor implements ClientMetaTableAccessor.CloseableVisitor {
     return this.previous == null || !this.previous.getTable().equals(ri.getTable());
   }
 
-  @Override
-  public void close() throws IOException {
+  public void done() {
     // This is a table transition... after the last region. Check previous.
     // Should be last region. If not, its a hole on end of laster table.
     if (this.previous != null && !this.previous.isLast()) {
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestSimpleMetaSplitMerge.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestSimpleMetaSplitMerge.java
index 9eb263a..5e174f1 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestSimpleMetaSplitMerge.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestSimpleMetaSplitMerge.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.hbase;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 import java.util.List;
@@ -31,6 +32,7 @@ import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.client.TableDescriptor;
 import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
+import org.apache.hadoop.hbase.master.assignment.RegionStateStore;
 import org.apache.hadoop.hbase.regionserver.HRegion;
 import org.apache.hadoop.hbase.regionserver.HStore;
 import org.apache.hadoop.hbase.testclassification.MediumTests;
@@ -95,6 +97,20 @@ public class TestSimpleMetaSplitMerge {
     }
   }
 
+  private void compactMeta() throws IOException {
+    for (JVMClusterUtil.RegionServerThread t : UTIL.getMiniHBaseCluster()
+      .getRegionServerThreads()) {
+      for (HRegion r : t.getRegionServer().getOnlineRegionsLocalContext()) {
+        if (TableName.isMetaTableName(r.getRegionInfo().getTable())) {
+          r.compact(true);
+          for (HStore store : r.getStores()) {
+            store.closeAndArchiveCompactedFiles();
+          }
+        }
+      }
+    }
+  }
+
   @Test
   public void test() throws Exception {
     try (Table table = UTIL.getConnection().getTable(TD1.getTableName())) {
@@ -104,6 +120,8 @@ public class TestSimpleMetaSplitMerge {
       table.put(new Put(Bytes.toBytes("row2")).addColumn(CF, CQ, Bytes.toBytes("row2")));
     }
     Admin admin = UTIL.getAdmin();
+    // turn off catalog janitor
+    admin.catalogJanitorSwitch(false);
     // split meta
     admin.split(TableName.META_TABLE_NAME, Bytes.toBytes("b"));
     assertMetaRegionCount(2);
@@ -115,17 +133,7 @@ public class TestSimpleMetaSplitMerge {
     List<RegionInfo> regions = admin.getRegions(TableName.META_TABLE_NAME);
     assertEquals(2, regions.size());
     // compact to make sure we can merge
-    for (JVMClusterUtil.RegionServerThread t : UTIL.getMiniHBaseCluster()
-      .getRegionServerThreads()) {
-      for (HRegion r : t.getRegionServer().getOnlineRegionsLocalContext()) {
-        if (TableName.isMetaTableName(r.getRegionInfo().getTable())) {
-          r.compact(true);
-          for (HStore store : r.getStores()) {
-            store.closeAndArchiveCompactedFiles();
-          }
-        }
-      }
-    }
+    compactMeta();
     // merge the 2 regions back to 1
     admin.mergeRegionsAsync(regions.stream().map(RegionInfo::getRegionName).toArray(byte[][]::new),
       false).get();
@@ -137,5 +145,17 @@ public class TestSimpleMetaSplitMerge {
     // make sure that we could still get the locations from the new meta region
     assertValue(TD2.getTableName(), "row2");
     assertValue(TD1.getTableName(), "row1");
+
+    // make sure that catalog janitor can clean up the merged regions
+    RegionStateStore regionStateStore =
+      UTIL.getHBaseCluster().getMaster().getAssignmentManager().getRegionStateStore();
+    RegionInfo mergedRegion = admin.getRegions(TableName.META_TABLE_NAME).get(0);
+    assertTrue(regionStateStore.hasMergeRegions(mergedRegion));
+    // compact to make sure we could clean the merged regions
+    compactMeta();
+    // one for merged region, one for split parent
+    assertEquals(2, admin.runCatalogJanitor());
+    // the gc procedure is run in background so we need to wait here, can not check directly
+    UTIL.waitFor(30000, () -> !regionStateStore.hasMergeRegions(mergedRegion));
   }
 }