Skip to content

Commit 316a441

Browse files
committed
HBASE-27125 The batch size of cleaning expired mob files should have an upper bound
1 parent b365748 commit 316a441

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
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
@@ -46,6 +46,9 @@ public final class MobConstants {
4646
public static final String MOB_CACHE_EVICT_REMAIN_RATIO = "hbase.mob.cache.evict.remain.ratio";
4747
public static final Tag MOB_REF_TAG =
4848
new ArrayBackedTag(TagType.MOB_REFERENCE_TAG_TYPE, HConstants.EMPTY_BYTE_ARRAY);
49+
public static final String MOB_CLEANER_BATCH_SIZE_UPPER_BOUND =
50+
"hbase.master.mob.cleaner.batch.size.upper.bound";
51+
public static final int DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND = 10000;
4952

5053
public static final float DEFAULT_EVICT_REMAIN_RATIO = 0.5f;
5154
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.nio.ByteBuffer;
@@ -314,20 +317,30 @@ public static void cleanExpiredMobFiles(FileSystem fs, Configuration conf, Table
314317
}
315318
filesToClean
316319
.add(new HStoreFile(fs, file.getPath(), conf, cacheConfig, BloomType.NONE, true));
320+
if (
321+
filesToClean.size() >= conf.getInt(MOB_CLEANER_BATCH_SIZE_UPPER_BOUND,
322+
DEFAULT_MOB_CLEANER_BATCH_SIZE_UPPER_BOUND)
323+
) {
324+
if (
325+
removeMobFiles(conf, fs, tableName, mobTableDir, columnDescriptor.getName(),
326+
filesToClean)
327+
) {
328+
deletedFileCount += filesToClean.size();
329+
}
330+
filesToClean.clear();
331+
}
317332
}
318333
} catch (Exception e) {
319334
LOG.error("Cannot parse the fileName " + fileName, e);
320335
}
321336
}
322-
if (!filesToClean.isEmpty()) {
323-
try {
324-
removeMobFiles(conf, fs, tableName, mobTableDir, columnDescriptor.getName(), filesToClean);
325-
deletedFileCount = filesToClean.size();
326-
} catch (IOException e) {
327-
LOG.error("Failed to delete the mob files " + filesToClean, e);
328-
}
337+
if (
338+
!filesToClean.isEmpty() && removeMobFiles(conf, fs, tableName, mobTableDir,
339+
columnDescriptor.getName(), filesToClean)
340+
) {
341+
deletedFileCount += filesToClean.size();
329342
}
330-
LOG.info("{} expired mob files are deleted", deletedFileCount);
343+
LOG.info("Table {} {} expired mob files in total are deleted", tableName, deletedFileCount);
331344
}
332345

333346
/**
@@ -459,10 +472,17 @@ public static boolean isMobRegionName(TableName tableName, byte[] regionName) {
459472
* @param family The name of the column family.
460473
* @param storeFiles The files to be deleted.
461474
*/
462-
public static void removeMobFiles(Configuration conf, FileSystem fs, TableName tableName,
463-
Path tableDir, byte[] family, Collection<HStoreFile> storeFiles) throws IOException {
464-
HFileArchiver.archiveStoreFiles(conf, fs, getMobRegionInfo(tableName), tableDir, family,
465-
storeFiles);
475+
public static boolean removeMobFiles(Configuration conf, FileSystem fs, TableName tableName,
476+
Path tableDir, byte[] family, Collection<HStoreFile> storeFiles) {
477+
try {
478+
HFileArchiver.archiveStoreFiles(conf, fs, getMobRegionInfo(tableName), tableDir, family,
479+
storeFiles);
480+
LOG.info("Table {} {} expired mob files are deleted", tableName, storeFiles.size());
481+
return true;
482+
} catch (IOException e) {
483+
LOG.error("Failed to delete the mob files, table {}", tableName, e);
484+
}
485+
return false;
466486
}
467487

468488
/**

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;
@@ -55,6 +56,7 @@ public class TestExpiredMobFileCleaner {
5556
private final static String family = "family";
5657
private final static byte[] row1 = Bytes.toBytes("row1");
5758
private final static byte[] row2 = Bytes.toBytes("row2");
59+
private final static byte[] row3 = Bytes.toBytes("row3");
5860
private final static byte[] qf = Bytes.toBytes("qf");
5961

6062
private static BufferedMutator table;
@@ -63,6 +65,7 @@ public class TestExpiredMobFileCleaner {
6365
@BeforeClass
6466
public static void setUpBeforeClass() throws Exception {
6567
TEST_UTIL.getConfiguration().setInt("hfile.format.version", 3);
68+
TEST_UTIL.getConfiguration().setInt(MOB_CLEANER_BATCH_SIZE_UPPER_BOUND, 2);
6669
}
6770

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

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

151162
// run the cleaner
@@ -156,7 +167,7 @@ public void testCleaner() throws Exception {
156167

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

0 commit comments

Comments
 (0)