HBASE-29568 - Allow for a configurable grace period when using Time Based Priority (#7425)
Signed-off-by: Wellington Chevreuil <wchevreuil@apache.org>
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DataTieringManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DataTieringManager.java
index 2a5e2a5..6638fd2 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DataTieringManager.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DataTieringManager.java
@@ -47,6 +47,9 @@
"hbase.regionserver.datatiering.enable";
public static final boolean DEFAULT_GLOBAL_DATA_TIERING_ENABLED = false; // disabled by default
public static final String DATATIERING_KEY = "hbase.hstore.datatiering.type";
+ public static final String HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY =
+ "hbase.hstore.datatiering.grace.period.millis";
+ public static final long DEFAULT_DATATIERING_GRACE_PERIOD = 0;
public static final String DATATIERING_HOT_DATA_AGE_KEY =
"hbase.hstore.datatiering.hot.age.millis";
public static final DataTieringType DEFAULT_DATATIERING = DataTieringType.NONE;
@@ -139,6 +142,9 @@
* @return {@code true} if the data is hot, {@code false} otherwise
*/
public boolean isHotData(long maxTimestamp, Configuration conf) {
+ if (isWithinGracePeriod(maxTimestamp, conf)) {
+ return true;
+ }
DataTieringType dataTieringType = getDataTieringType(conf);
if (
@@ -170,8 +176,11 @@
throw new DataTieringException(
"Store file corresponding to " + hFilePath + " doesn't exist");
}
- return hotDataValidator(dataTieringType.getInstance().getTimestamp(getHStoreFile(hFilePath)),
- getDataTieringHotDataAge(configuration));
+ long maxTimestamp = dataTieringType.getInstance().getTimestamp(hStoreFile);
+ if (isWithinGracePeriod(maxTimestamp, configuration)) {
+ return true;
+ }
+ return hotDataValidator(maxTimestamp, getDataTieringHotDataAge(configuration));
}
// DataTieringType.NONE or other types are considered hot by default
return true;
@@ -189,13 +198,21 @@
public boolean isHotData(HFileInfo hFileInfo, Configuration configuration) {
DataTieringType dataTieringType = getDataTieringType(configuration);
if (hFileInfo != null && !dataTieringType.equals(DataTieringType.NONE)) {
- return hotDataValidator(dataTieringType.getInstance().getTimestamp(hFileInfo),
- getDataTieringHotDataAge(configuration));
+ long maxTimestamp = dataTieringType.getInstance().getTimestamp(hFileInfo);
+ if (isWithinGracePeriod(maxTimestamp, configuration)) {
+ return true;
+ }
+ return hotDataValidator(maxTimestamp, getDataTieringHotDataAge(configuration));
}
// DataTieringType.NONE or other types are considered hot by default
return true;
}
+ private boolean isWithinGracePeriod(long maxTimestamp, Configuration conf) {
+ long gracePeriod = getDataTieringGracePeriod(conf);
+ return gracePeriod > 0 && (getCurrentTimestamp() - maxTimestamp) < gracePeriod;
+ }
+
private boolean hotDataValidator(long maxTimestamp, long hotDataAge) {
long currentTimestamp = getCurrentTimestamp();
long diff = currentTimestamp - maxTimestamp;
@@ -275,6 +292,11 @@
conf.get(DATATIERING_HOT_DATA_AGE_KEY, String.valueOf(DEFAULT_DATATIERING_HOT_DATA_AGE)));
}
+ private long getDataTieringGracePeriod(Configuration conf) {
+ return Long.parseLong(conf.get(HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY,
+ String.valueOf(DEFAULT_DATATIERING_GRACE_PERIOD)));
+ }
+
/*
* This API traverses through the list of online regions and returns a subset of these files-names
* that are cold.
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestDataTieringManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestDataTieringManager.java
index bf82a53..cdf00e5 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestDataTieringManager.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestDataTieringManager.java
@@ -232,6 +232,57 @@
}
@Test
+ public void testGracePeriodMakesColdFileHot() throws IOException, DataTieringException {
+ initializeTestEnvironment();
+
+ long hotAge = 1 * DAY;
+ long gracePeriod = 3 * DAY;
+
+ long currentTime = System.currentTimeMillis();
+ long fileTimestamp = currentTime - (2 * DAY);
+
+ Configuration conf = getConfWithGracePeriod(hotAge, gracePeriod);
+ HRegion region = createHRegion("tableGracePeriod", conf);
+ HStore hStore = createHStore(region, "cf1", conf);
+
+ HStoreFile file = createHStoreFile(hStore.getStoreContext().getFamilyStoreDirectoryPath(),
+ hStore.getReadOnlyConfiguration(), fileTimestamp, region.getRegionFileSystem());
+ file.initReader();
+
+ hStore.refreshStoreFiles();
+ region.stores.put(Bytes.toBytes("cf1"), hStore);
+ testOnlineRegions.put(region.getRegionInfo().getEncodedName(), region);
+ Path hFilePath = file.getPath();
+ assertTrue("File should be hot due to grace period", dataTieringManager.isHotData(hFilePath));
+ }
+
+ @Test
+ public void testFileIsColdWithoutGracePeriod() throws IOException, DataTieringException {
+ initializeTestEnvironment();
+
+ long hotAge = 1 * DAY;
+ long gracePeriod = 0;
+ long currentTime = System.currentTimeMillis();
+ long fileTimestamp = currentTime - (2 * DAY);
+
+ Configuration conf = getConfWithGracePeriod(hotAge, gracePeriod);
+ HRegion region = createHRegion("tableNoGracePeriod", conf);
+ HStore hStore = createHStore(region, "cf1", conf);
+
+ HStoreFile file = createHStoreFile(hStore.getStoreContext().getFamilyStoreDirectoryPath(),
+ hStore.getReadOnlyConfiguration(), fileTimestamp, region.getRegionFileSystem());
+ file.initReader();
+
+ hStore.refreshStoreFiles();
+ region.stores.put(Bytes.toBytes("cf1"), hStore);
+ testOnlineRegions.put(region.getRegionInfo().getEncodedName(), region);
+
+ Path hFilePath = file.getPath();
+ assertFalse("File should be cold without grace period",
+ dataTieringManager.isHotData(hFilePath));
+ }
+
+ @Test
public void testPrefetchWhenDataTieringEnabled() throws IOException {
setPrefetchBlocksOnOpen();
initializeTestEnvironment();
@@ -770,6 +821,8 @@
.setValue(DataTieringManager.DATATIERING_KEY, conf.get(DataTieringManager.DATATIERING_KEY))
.setValue(DataTieringManager.DATATIERING_HOT_DATA_AGE_KEY,
conf.get(DataTieringManager.DATATIERING_HOT_DATA_AGE_KEY))
+ .setValue(DataTieringManager.HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY,
+ conf.get(DataTieringManager.HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY))
.build();
RegionInfo hri = RegionInfoBuilder.newBuilder(tableName).build();
@@ -797,6 +850,8 @@
.setValue(DataTieringManager.DATATIERING_KEY, conf.get(DataTieringManager.DATATIERING_KEY))
.setValue(DataTieringManager.DATATIERING_HOT_DATA_AGE_KEY,
conf.get(DataTieringManager.DATATIERING_HOT_DATA_AGE_KEY))
+ .setValue(DataTieringManager.HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY,
+ conf.get(DataTieringManager.HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY))
.build();
return new HStore(region, columnFamilyDescriptor, conf, false);
@@ -809,6 +864,13 @@
return conf;
}
+ private static Configuration getConfWithGracePeriod(long hotDataAge, long gracePeriod) {
+ Configuration conf = getConfWithTimeRangeDataTieringEnabled(hotDataAge);
+ conf.set(DataTieringManager.HSTORE_DATATIERING_GRACE_PERIOD_MILLIS_KEY,
+ String.valueOf(gracePeriod));
+ return conf;
+ }
+
static HStoreFile createHStoreFile(Path storeDir, Configuration conf, long timestamp,
HRegionFileSystem regionFs) throws IOException {
String columnFamily = storeDir.getName();