You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ha...@apache.org on 2022/06/17 18:09:12 UTC

[hbase] branch branch-2.4 updated: HBASE-27125 The batch size of cleaning expired mob files should have an upper bound (#4541)

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

haxiaolin pushed a commit to branch branch-2.4
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-2.4 by this push:
     new 15a88efb17 HBASE-27125 The batch size of cleaning expired mob files should have an upper bound (#4541)
15a88efb17 is described below

commit 15a88efb1793cbbe8e15d9330fd9feb87f9b2a92
Author: Xiaolin Ha <ha...@apache.org>
AuthorDate: Fri Jun 17 23:35:26 2022 +0800

    HBASE-27125 The batch size of cleaning expired mob files should have an upper bound (#4541)
    
    Signed-off-by: Duo Zhang <zh...@apache.org>
---
 .../org/apache/hadoop/hbase/mob/MobConstants.java  |  3 ++
 .../java/org/apache/hadoop/hbase/mob/MobUtils.java | 44 ++++++++++++++++------
 .../mob/compactions/PartitionedMobCompactor.java   | 30 ++++++---------
 .../hbase/mob/TestExpiredMobFileCleaner.java       | 13 ++++++-
 4 files changed, 58 insertions(+), 32 deletions(-)

diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobConstants.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobConstants.java
index 19bcf6a93e..8f2f246866 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobConstants.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobConstants.java
@@ -49,6 +49,9 @@ public final class MobConstants {
   public static final String MOB_CACHE_EVICT_REMAIN_RATIO = "hbase.mob.cache.evict.remain.ratio";
   public static final Tag MOB_REF_TAG =
     new ArrayBackedTag(TagType.MOB_REFERENCE_TAG_TYPE, HConstants.EMPTY_BYTE_ARRAY);
+  public static final String MOB_CLEANER_BATCH_SIZE_UPPER_BOUND =
+    "hbase.master.mob.cleaner.batch.size.upper.bound";
+  public static final int DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND = 10000;
 
   public static final float DEFAULT_EVICT_REMAIN_RATIO = 0.5f;
   public static final long DEFAULT_MOB_CACHE_EVICT_PERIOD = 3600L;
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobUtils.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobUtils.java
index 4d536c70ad..6a981c61f1 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobUtils.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobUtils.java
@@ -17,6 +17,9 @@
  */
 package org.apache.hadoop.hbase.mob;
 
+import static org.apache.hadoop.hbase.mob.MobConstants.DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND;
+import static org.apache.hadoop.hbase.mob.MobConstants.MOB_CLEANER_BATCH_SIZE_UPPER_BOUND;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.text.ParseException;
@@ -331,20 +334,30 @@ public final class MobUtils {
           }
           filesToClean
             .add(new HStoreFile(fs, file.getPath(), conf, cacheConfig, BloomType.NONE, true));
+          if (
+            filesToClean.size() >= conf.getInt(MOB_CLEANER_BATCH_SIZE_UPPER_BOUND,
+              DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND)
+          ) {
+            if (
+              removeMobFiles(conf, fs, tableName, mobTableDir, columnDescriptor.getName(),
+                filesToClean)
+            ) {
+              deletedFileCount += filesToClean.size();
+            }
+            filesToClean.clear();
+          }
         }
       } catch (Exception e) {
         LOG.error("Cannot parse the fileName " + fileName, e);
       }
     }
-    if (!filesToClean.isEmpty()) {
-      try {
-        removeMobFiles(conf, fs, tableName, mobTableDir, columnDescriptor.getName(), filesToClean);
-        deletedFileCount = filesToClean.size();
-      } catch (IOException e) {
-        LOG.error("Failed to delete the mob files " + filesToClean, e);
-      }
+    if (
+      !filesToClean.isEmpty() && removeMobFiles(conf, fs, tableName, mobTableDir,
+        columnDescriptor.getName(), filesToClean)
+    ) {
+      deletedFileCount += filesToClean.size();
     }
-    LOG.info(deletedFileCount + " expired mob files are deleted");
+    LOG.info("Table {} {} expired mob files in total are deleted", tableName, deletedFileCount);
   }
 
   /**
@@ -487,10 +500,17 @@ public final class MobUtils {
    * @param family     The name of the column family.
    * @param storeFiles The files to be deleted.
    */
-  public static void removeMobFiles(Configuration conf, FileSystem fs, TableName tableName,
-    Path tableDir, byte[] family, Collection<HStoreFile> storeFiles) throws IOException {
-    HFileArchiver.archiveStoreFiles(conf, fs, getMobRegionInfo(tableName), tableDir, family,
-      storeFiles);
+  public static boolean removeMobFiles(Configuration conf, FileSystem fs, TableName tableName,
+    Path tableDir, byte[] family, Collection<HStoreFile> storeFiles) {
+    try {
+      HFileArchiver.archiveStoreFiles(conf, fs, getMobRegionInfo(tableName), tableDir, family,
+        storeFiles);
+      LOG.info("Table {} {} expired mob files are deleted", tableName, storeFiles.size());
+      return true;
+    } catch (IOException e) {
+      LOG.error("Failed to delete the mob files, table {}", tableName, e);
+    }
+    return false;
   }
 
   /**
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/compactions/PartitionedMobCompactor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/compactions/PartitionedMobCompactor.java
index 04f9d7e660..4f43fd8b30 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/compactions/PartitionedMobCompactor.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/mob/compactions/PartitionedMobCompactor.java
@@ -365,14 +365,14 @@ public class PartitionedMobCompactor extends MobCompactor {
         + "table='{}' and column='{}'", tableName, column.getNameAsString());
       for (CompactionDelPartition delPartition : request.getDelPartitions()) {
         LOG.info(Objects.toString(delPartition.listDelFiles()));
-        try {
-          MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
-            delPartition.getStoreFiles());
-        } catch (IOException e) {
+        if (
+          !MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
+            delPartition.getStoreFiles())
+        ) {
           LOG.error(
             "Failed to archive the del files {} for partition {} table='{}' and " + "column='{}'",
-            delPartition.getStoreFiles(), delPartition.getId(), tableName, column.getNameAsString(),
-            e);
+            delPartition.getStoreFiles(), delPartition.getId(), tableName,
+            column.getNameAsString());
         }
       }
     }
@@ -695,14 +695,10 @@ public class PartitionedMobCompactor extends MobCompactor {
       }
 
       // archive the old mob files, do not archive the del files.
-      try {
-        closeStoreFileReaders(mobFilesToCompact);
-        closeReaders = false;
-        MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
-          mobFilesToCompact);
-      } catch (IOException e) {
-        LOG.error("Failed to archive the files " + mobFilesToCompact, e);
-      }
+      closeStoreFileReaders(mobFilesToCompact);
+      closeReaders = false;
+      MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
+        mobFilesToCompact);
     } finally {
       if (closeReaders) {
         closeStoreFileReaders(mobFilesToCompact);
@@ -811,11 +807,7 @@ public class PartitionedMobCompactor extends MobCompactor {
     // commit the new del file
     Path path = MobUtils.commitFile(conf, fs, filePath, mobFamilyDir, compactionCacheConfig);
     // archive the old del files
-    try {
-      MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(), delFiles);
-    } catch (IOException e) {
-      LOG.error("Failed to archive the old del files " + delFiles, e);
-    }
+    MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(), delFiles);
     return path;
   }
 
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/mob/TestExpiredMobFileCleaner.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/mob/TestExpiredMobFileCleaner.java
index 96f9ec8130..d64551e00b 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/mob/TestExpiredMobFileCleaner.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/mob/TestExpiredMobFileCleaner.java
@@ -17,6 +17,7 @@
  */
 package org.apache.hadoop.hbase.mob;
 
+import static org.apache.hadoop.hbase.mob.MobConstants.MOB_CLEANER_BATCH_SIZE_UPPER_BOUND;
 import static org.junit.Assert.assertEquals;
 
 import org.apache.hadoop.fs.FileStatus;
@@ -53,6 +54,7 @@ public class TestExpiredMobFileCleaner {
   private final static String family = "family";
   private final static byte[] row1 = Bytes.toBytes("row1");
   private final static byte[] row2 = Bytes.toBytes("row2");
+  private final static byte[] row3 = Bytes.toBytes("row3");
   private final static byte[] qf = Bytes.toBytes("qf");
 
   private static BufferedMutator table;
@@ -61,6 +63,7 @@ public class TestExpiredMobFileCleaner {
   @BeforeClass
   public static void setUpBeforeClass() throws Exception {
     TEST_UTIL.getConfiguration().setInt("hfile.format.version", 3);
+    TEST_UTIL.getConfiguration().setInt(MOB_CLEANER_BATCH_SIZE_UPPER_BOUND, 2);
   }
 
   @AfterClass
@@ -146,6 +149,14 @@ public class TestExpiredMobFileCleaner {
     String f2 = secondFiles[1].getPath().getName();
     String secondFile = f1.equals(firstFile) ? f2 : f1;
 
+    ts = EnvironmentEdgeManager.currentTime() - 4 * secondsOfDay() * 1000; // 4 days before
+    putKVAndFlush(table, row3, dummyData, ts);
+    ts = EnvironmentEdgeManager.currentTime() - 4 * secondsOfDay() * 1000; // 4 days before
+    putKVAndFlush(table, row3, dummyData, ts);
+    FileStatus[] thirdFiles = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
+    // now there are 4 mob files
+    assertEquals("Before cleanup without delay 3", 4, thirdFiles.length);
+
     modifyColumnExpiryDays(2); // ttl = 2, make the first row expired
 
     // run the cleaner
@@ -156,7 +167,7 @@ public class TestExpiredMobFileCleaner {
 
     FileStatus[] filesAfterClean = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
     String lastFile = filesAfterClean[0].getPath().getName();
-    // the first mob fie is removed
+    // there are 4 mob files in total, but only 3 need to be cleaned
     assertEquals("After cleanup without delay 1", 1, filesAfterClean.length);
     assertEquals("After cleanup without delay 2", secondFile, lastFile);
   }