Skip to content

Commit f7d2d12

Browse files
committed
HBASE-27125 The batch size of cleaning expired mob files should have an upper bound (#4541)
Signed-off-by: Duo Zhang <[email protected]>
1 parent ef0ff27 commit f7d2d12

File tree

4 files changed

+58
-32
lines changed

4 files changed

+58
-32
lines changed

hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public final class MobConstants {
4949
public static final String MOB_CACHE_EVICT_REMAIN_RATIO = "hbase.mob.cache.evict.remain.ratio";
5050
public static final Tag MOB_REF_TAG =
5151
new ArrayBackedTag(TagType.MOB_REFERENCE_TAG_TYPE, HConstants.EMPTY_BYTE_ARRAY);
52+
public static final String MOB_CLEANER_BATCH_SIZE_UPPER_BOUND =
53+
"hbase.master.mob.cleaner.batch.size.upper.bound";
54+
public static final int DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND = 10000;
5255

5356
public static final float DEFAULT_EVICT_REMAIN_RATIO = 0.5f;
5457
public static final long DEFAULT_MOB_CACHE_EVICT_PERIOD = 3600L;

hbase-server/src/main/java/org/apache/hadoop/hbase/mob/MobUtils.java

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
*/
1818
package org.apache.hadoop.hbase.mob;
1919

20+
import static org.apache.hadoop.hbase.mob.MobConstants.DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND;
21+
import static org.apache.hadoop.hbase.mob.MobConstants.MOB_CLEANER_BATCH_SIZE_UPPER_BOUND;
22+
2023
import java.io.FileNotFoundException;
2124
import java.io.IOException;
2225
import java.text.ParseException;
@@ -331,20 +334,30 @@ public static void cleanExpiredMobFiles(FileSystem fs, Configuration conf, Table
331334
}
332335
filesToClean
333336
.add(new HStoreFile(fs, file.getPath(), conf, cacheConfig, BloomType.NONE, true));
337+
if (
338+
filesToClean.size() >= conf.getInt(MOB_CLEANER_BATCH_SIZE_UPPER_BOUND,
339+
DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND)
340+
) {
341+
if (
342+
removeMobFiles(conf, fs, tableName, mobTableDir, columnDescriptor.getName(),
343+
filesToClean)
344+
) {
345+
deletedFileCount += filesToClean.size();
346+
}
347+
filesToClean.clear();
348+
}
334349
}
335350
} catch (Exception e) {
336351
LOG.error("Cannot parse the fileName " + fileName, e);
337352
}
338353
}
339-
if (!filesToClean.isEmpty()) {
340-
try {
341-
removeMobFiles(conf, fs, tableName, mobTableDir, columnDescriptor.getName(), filesToClean);
342-
deletedFileCount = filesToClean.size();
343-
} catch (IOException e) {
344-
LOG.error("Failed to delete the mob files " + filesToClean, e);
345-
}
354+
if (
355+
!filesToClean.isEmpty() && removeMobFiles(conf, fs, tableName, mobTableDir,
356+
columnDescriptor.getName(), filesToClean)
357+
) {
358+
deletedFileCount += filesToClean.size();
346359
}
347-
LOG.info(deletedFileCount + " expired mob files are deleted");
360+
LOG.info("Table {} {} expired mob files in total are deleted", tableName, deletedFileCount);
348361
}
349362

350363
/**
@@ -487,10 +500,17 @@ public static Path getCompactionWorkingPath(Path root, String jobName) {
487500
* @param family The name of the column family.
488501
* @param storeFiles The files to be deleted.
489502
*/
490-
public static void removeMobFiles(Configuration conf, FileSystem fs, TableName tableName,
491-
Path tableDir, byte[] family, Collection<HStoreFile> storeFiles) throws IOException {
492-
HFileArchiver.archiveStoreFiles(conf, fs, getMobRegionInfo(tableName), tableDir, family,
493-
storeFiles);
503+
public static boolean removeMobFiles(Configuration conf, FileSystem fs, TableName tableName,
504+
Path tableDir, byte[] family, Collection<HStoreFile> storeFiles) {
505+
try {
506+
HFileArchiver.archiveStoreFiles(conf, fs, getMobRegionInfo(tableName), tableDir, family,
507+
storeFiles);
508+
LOG.info("Table {} {} expired mob files are deleted", tableName, storeFiles.size());
509+
return true;
510+
} catch (IOException e) {
511+
LOG.error("Failed to delete the mob files, table {}", tableName, e);
512+
}
513+
return false;
494514
}
495515

496516
/**

hbase-server/src/main/java/org/apache/hadoop/hbase/mob/compactions/PartitionedMobCompactor.java

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -365,14 +365,14 @@ protected List<Path> performCompaction(PartitionedMobCompactionRequest request)
365365
+ "table='{}' and column='{}'", tableName, column.getNameAsString());
366366
for (CompactionDelPartition delPartition : request.getDelPartitions()) {
367367
LOG.info(Objects.toString(delPartition.listDelFiles()));
368-
try {
369-
MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
370-
delPartition.getStoreFiles());
371-
} catch (IOException e) {
368+
if (
369+
!MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
370+
delPartition.getStoreFiles())
371+
) {
372372
LOG.error(
373373
"Failed to archive the del files {} for partition {} table='{}' and " + "column='{}'",
374-
delPartition.getStoreFiles(), delPartition.getId(), tableName, column.getNameAsString(),
375-
e);
374+
delPartition.getStoreFiles(), delPartition.getId(), tableName,
375+
column.getNameAsString());
376376
}
377377
}
378378
}
@@ -695,14 +695,10 @@ private void compactMobFilesInBatch(PartitionedMobCompactionRequest request,
695695
}
696696

697697
// archive the old mob files, do not archive the del files.
698-
try {
699-
closeStoreFileReaders(mobFilesToCompact);
700-
closeReaders = false;
701-
MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
702-
mobFilesToCompact);
703-
} catch (IOException e) {
704-
LOG.error("Failed to archive the files " + mobFilesToCompact, e);
705-
}
698+
closeStoreFileReaders(mobFilesToCompact);
699+
closeReaders = false;
700+
MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(),
701+
mobFilesToCompact);
706702
} finally {
707703
if (closeReaders) {
708704
closeStoreFileReaders(mobFilesToCompact);
@@ -811,11 +807,7 @@ private Path compactDelFilesInBatch(PartitionedMobCompactionRequest request,
811807
// commit the new del file
812808
Path path = MobUtils.commitFile(conf, fs, filePath, mobFamilyDir, compactionCacheConfig);
813809
// archive the old del files
814-
try {
815-
MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(), delFiles);
816-
} catch (IOException e) {
817-
LOG.error("Failed to archive the old del files " + delFiles, e);
818-
}
810+
MobUtils.removeMobFiles(conf, fs, tableName, mobTableDir, column.getName(), delFiles);
819811
return path;
820812
}
821813

hbase-server/src/test/java/org/apache/hadoop/hbase/mob/TestExpiredMobFileCleaner.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package org.apache.hadoop.hbase.mob;
1919

20+
import static org.apache.hadoop.hbase.mob.MobConstants.MOB_CLEANER_BATCH_SIZE_UPPER_BOUND;
2021
import static org.junit.Assert.assertEquals;
2122

2223
import org.apache.hadoop.fs.FileStatus;
@@ -54,6 +55,7 @@ public class TestExpiredMobFileCleaner {
5455
private final static String family = "family";
5556
private final static byte[] row1 = Bytes.toBytes("row1");
5657
private final static byte[] row2 = Bytes.toBytes("row2");
58+
private final static byte[] row3 = Bytes.toBytes("row3");
5759
private final static byte[] qf = Bytes.toBytes("qf");
5860

5961
private static BufferedMutator table;
@@ -62,6 +64,7 @@ public class TestExpiredMobFileCleaner {
6264
@BeforeClass
6365
public static void setUpBeforeClass() throws Exception {
6466
TEST_UTIL.getConfiguration().setInt("hfile.format.version", 3);
67+
TEST_UTIL.getConfiguration().setInt(MOB_CLEANER_BATCH_SIZE_UPPER_BOUND, 2);
6568
}
6669

6770
@AfterClass
@@ -147,6 +150,14 @@ public void testCleaner() throws Exception {
147150
String f2 = secondFiles[1].getPath().getName();
148151
String secondFile = f1.equals(firstFile) ? f2 : f1;
149152

153+
ts = EnvironmentEdgeManager.currentTime() - 4 * secondsOfDay() * 1000; // 4 days before
154+
putKVAndFlush(table, row3, dummyData, ts);
155+
ts = EnvironmentEdgeManager.currentTime() - 4 * secondsOfDay() * 1000; // 4 days before
156+
putKVAndFlush(table, row3, dummyData, ts);
157+
FileStatus[] thirdFiles = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
158+
// now there are 4 mob files
159+
assertEquals("Before cleanup without delay 3", 4, thirdFiles.length);
160+
150161
modifyColumnExpiryDays(2); // ttl = 2, make the first row expired
151162

152163
// run the cleaner
@@ -157,7 +168,7 @@ public void testCleaner() throws Exception {
157168

158169
FileStatus[] filesAfterClean = TEST_UTIL.getTestFileSystem().listStatus(mobDirPath);
159170
String lastFile = filesAfterClean[0].getPath().getName();
160-
// the first mob fie is removed
171+
// there are 4 mob files in total, but only 3 need to be cleaned
161172
assertEquals("After cleanup without delay 1", 1, filesAfterClean.length);
162173
assertEquals("After cleanup without delay 2", secondFile, lastFile);
163174
}

0 commit comments

Comments
 (0)