HBASE-27125 The batch size of cleaning expired mob files should have an upper bound (#4541)
Signed-off-by: Duo Zhang <zhangduo@apache.org>
This commit is contained in:
parent
ef0ff2729c
commit
f7d2d12ac1
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -54,6 +55,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;
|
||||
|
@ -62,6 +64,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
|
||||
|
@ -147,6 +150,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
|
||||
|
@ -157,7 +168,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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue