Skip to content

Commit 0f5d045

Browse files
committed
HBASE-24408 Introduce a general 'local region' to store data on master
1 parent 80b64ef commit 0f5d045

38 files changed

+1704
-782
lines changed

hbase-common/src/main/resources/hbase-default.xml

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ possible configurations would overwhelm and obscure the important.
125125
</property>
126126
<property>
127127
<name>hbase.master.logcleaner.plugins</name>
128-
<value>org.apache.hadoop.hbase.master.cleaner.TimeToLiveLogCleaner,org.apache.hadoop.hbase.master.cleaner.TimeToLiveProcedureWALCleaner</value>
128+
<value>org.apache.hadoop.hbase.master.cleaner.TimeToLiveLogCleaner,org.apache.hadoop.hbase.master.cleaner.TimeToLiveProcedureWALCleaner,org.apache.hadoop.hbase.master.cleaner.TimeToLiveMasterLocalStoreWALCleaner</value>
129129
<description>A comma-separated list of BaseLogCleanerDelegate invoked by
130130
the LogsCleaner service. These WAL cleaners are called in order,
131131
so put the cleaner that prunes the most files in front. To
@@ -139,16 +139,9 @@ possible configurations would overwhelm and obscure the important.
139139
<description>How long a WAL remain in the archive ({hbase.rootdir}/oldWALs) directory,
140140
after which it will be cleaned by a Master thread. The value is in milliseconds.</description>
141141
</property>
142-
<property>
143-
<name>hbase.master.procedurewalcleaner.ttl</name>
144-
<value>604800000</value>
145-
<description>How long a Procedure WAL will remain in the
146-
archive directory, after which it will be cleaned
147-
by a Master thread. The value is in milliseconds.</description>
148-
</property>
149142
<property>
150143
<name>hbase.master.hfilecleaner.plugins</name>
151-
<value>org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner</value>
144+
<value>org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner,org.apache.hadoop.hbase.master.cleaner.TimeToLiveMasterLocalStoreHFileCleaner</value>
152145
<description>A comma-separated list of BaseHFileCleanerDelegate invoked by
153146
the HFileCleaner service. These HFiles cleaners are called in order,
154147
so put the cleaner that prunes the most files in front. To
@@ -157,17 +150,6 @@ possible configurations would overwhelm and obscure the important.
157150
default hfile cleaners in the list as they will be overwritten in
158151
hbase-site.xml.</description>
159152
</property>
160-
<property>
161-
<name>hbase.procedure.store.region.hfilecleaner.plugins</name>
162-
<value>org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner</value>
163-
<description>A comma-separated list of BaseHFileCleanerDelegate invoked by
164-
the RegionProcedureStore HFileCleaner service. These HFiles cleaners are
165-
called in order, so put the cleaner that prunes the most files in front. To
166-
implement your own BaseHFileCleanerDelegate, just put it in HBase's classpath
167-
and add the fully qualified class name here. Always add the above
168-
default hfile cleaners in the list as they will be overwritten in
169-
hbase-site.xml.</description>
170-
</property>
171153
<property>
172154
<name>hbase.master.infoserver.redirect</name>
173155
<value>true</value>

hbase-procedure/src/main/java/org/apache/hadoop/hbase/procedure2/store/ProcedureStore.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,12 @@ public interface ProcedureLoader {
186186

187187
/**
188188
* Acquire the lease for the procedure store.
189+
* @deprecated since 2.3.0, will be removed in 4.0.0 along with
190+
* {@link org.apache.hadoop.hbase.procedure2.store.wal.WALProcedureStore}. As now we
191+
* will store the procedure data in a master local region, and master itself will deal
192+
* with the lease recovery of the region.
189193
*/
194+
@Deprecated
190195
void recoverLease() throws IOException;
191196

192197
/**

hbase-server/src/main/java/org/apache/hadoop/hbase/io/FileLink.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,12 +521,13 @@ public static String getBackReferenceFileName(final Path dirPath) {
521521

522522
/**
523523
* Checks if the specified directory path is a back reference links folder.
524-
*
525524
* @param dirPath Directory path to verify
526525
* @return True if the specified directory is a link references folder
527526
*/
528527
public static boolean isBackReferencesDir(final Path dirPath) {
529-
if (dirPath == null) return false;
528+
if (dirPath == null) {
529+
return false;
530+
}
530531
return dirPath.getName().startsWith(BACK_REFERENCES_DIRECTORY_PREFIX);
531532
}
532533

hbase-server/src/main/java/org/apache/hadoop/hbase/io/HFileLink.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ public static boolean isHFileLink(final Path path) {
209209
*/
210210
public static boolean isHFileLink(String fileName) {
211211
Matcher m = LINK_NAME_PATTERN.matcher(fileName);
212-
if (!m.matches()) return false;
212+
if (!m.matches()) {
213+
return false;
214+
}
213215
return m.groupCount() > 2 && m.group(4) != null && m.group(3) != null && m.group(2) != null;
214216
}
215217

hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
import org.apache.hadoop.hbase.master.replication.UpdatePeerConfigProcedure;
145145
import org.apache.hadoop.hbase.master.slowlog.SlowLogMasterService;
146146
import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
147+
import org.apache.hadoop.hbase.master.store.LocalStore;
147148
import org.apache.hadoop.hbase.master.zksyncer.MasterAddressSyncer;
148149
import org.apache.hadoop.hbase.master.zksyncer.MetaLocationSyncer;
149150
import org.apache.hadoop.hbase.mob.MobFileCleanerChore;
@@ -449,6 +450,9 @@ public void run() {
449450
private ProcedureExecutor<MasterProcedureEnv> procedureExecutor;
450451
private ProcedureStore procedureStore;
451452

453+
// the master local storage to store procedure data, etc.
454+
private LocalStore localStore;
455+
452456
// handle table states
453457
private TableStateManager tableStateManager;
454458

@@ -913,7 +917,8 @@ private void finishActiveMasterInitialization(MonitoredTask status) throws IOExc
913917
this.masterActiveTime = System.currentTimeMillis();
914918
// TODO: Do this using Dependency Injection, using PicoContainer, Guice or Spring.
915919

916-
// always initialize the MemStoreLAB as we use a region to store procedure now.
920+
// always initialize the MemStoreLAB as we use a region to store data in master now, see
921+
// localStore.
917922
initializeMemStoreChunkCreator();
918923
this.fileSystemManager = new MasterFileSystem(conf);
919924
this.walManager = new MasterWalManager(this);
@@ -959,6 +964,9 @@ private void finishActiveMasterInitialization(MonitoredTask status) throws IOExc
959964
DEFAULT_HBASE_SPLIT_COORDINATED_BY_ZK)) {
960965
this.splitWALManager = new SplitWALManager(this);
961966
}
967+
968+
// initialize local store
969+
localStore = LocalStore.create(this);
962970
createProcedureExecutor();
963971
Map<Class<?>, List<Procedure<MasterProcedureEnv>>> procsByType =
964972
procedureExecutor.getActiveProceduresNoCopy().stream()
@@ -1447,6 +1455,8 @@ private void startServiceThreads() throws IOException {
14471455
this.executorService.startExecutorService(ExecutorType.MASTER_TABLE_OPERATIONS, 1);
14481456
startProcedureExecutor();
14491457

1458+
// Create cleaner thread pool
1459+
cleanerPool = new DirScanPool(conf);
14501460
// Start log cleaner thread
14511461
int cleanerInterval =
14521462
conf.getInt(HBASE_MASTER_CLEANER_INTERVAL, DEFAULT_HBASE_MASTER_CLEANER_INTERVAL);
@@ -1534,6 +1544,9 @@ protected void stopServiceThreads() {
15341544

15351545
stopProcedureExecutor();
15361546

1547+
if (localStore != null) {
1548+
localStore.close(isAborted());
1549+
}
15371550
if (this.walManager != null) {
15381551
this.walManager.stop();
15391552
}
@@ -1550,10 +1563,8 @@ protected void stopServiceThreads() {
15501563

15511564
private void createProcedureExecutor() throws IOException {
15521565
MasterProcedureEnv procEnv = new MasterProcedureEnv(this);
1553-
// Create cleaner thread pool
1554-
cleanerPool = new DirScanPool(conf);
1555-
procedureStore = new RegionProcedureStore(this, cleanerPool,
1556-
new MasterProcedureEnv.FsUtilsLeaseRecovery(this));
1566+
procedureStore =
1567+
new RegionProcedureStore(this, localStore, new MasterProcedureEnv.FsUtilsLeaseRecovery(this));
15571568
procedureStore.registerListener(new ProcedureStoreListener() {
15581569

15591570
@Override
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hbase.master.cleaner;
19+
20+
import java.time.Instant;
21+
import java.time.ZoneOffset;
22+
import java.time.format.DateTimeFormatter;
23+
import org.apache.hadoop.conf.Configuration;
24+
import org.apache.hadoop.fs.FileStatus;
25+
import org.apache.hadoop.fs.Path;
26+
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
27+
import org.apache.yetus.audience.InterfaceAudience;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
31+
/**
32+
* Base class for time to live file cleaner.
33+
*/
34+
@InterfaceAudience.Private
35+
public abstract class BaseTimeToLiveFileCleaner extends BaseLogCleanerDelegate {
36+
37+
private static final Logger LOG =
38+
LoggerFactory.getLogger(BaseTimeToLiveFileCleaner.class.getName());
39+
40+
private static final DateTimeFormatter FORMATTER =
41+
DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.systemDefault());
42+
43+
// Configured time a log can be kept after it was closed
44+
private long ttlMs;
45+
46+
private volatile boolean stopped = false;
47+
48+
@Override
49+
public final void setConf(Configuration conf) {
50+
super.setConf(conf);
51+
this.ttlMs = getTtlMs(conf);
52+
}
53+
54+
@Override
55+
public boolean isFileDeletable(FileStatus status) {
56+
// Files are validated for the second time here,
57+
// if it causes a bottleneck this logic needs refactored
58+
if (!valiateFilename(status.getPath())) {
59+
return true;
60+
}
61+
long currentTime = EnvironmentEdgeManager.currentTime();
62+
long time = status.getModificationTime();
63+
long life = currentTime - time;
64+
65+
if (LOG.isTraceEnabled()) {
66+
LOG.trace("File life:{}ms, ttl:{}ms, current:{}, from{}", life, ttlMs,
67+
FORMATTER.format(Instant.ofEpochMilli(currentTime)),
68+
FORMATTER.format(Instant.ofEpochMilli(time)));
69+
}
70+
if (life < 0) {
71+
LOG.warn("Found a file ({}) newer than current time ({} < {}), probably a clock skew",
72+
status.getPath(), FORMATTER.format(Instant.ofEpochMilli(currentTime)),
73+
FORMATTER.format(Instant.ofEpochMilli(time)));
74+
return false;
75+
}
76+
return life > ttlMs;
77+
}
78+
79+
@Override
80+
public void stop(String why) {
81+
this.stopped = true;
82+
}
83+
84+
@Override
85+
public boolean isStopped() {
86+
return this.stopped;
87+
}
88+
89+
protected abstract long getTtlMs(Configuration conf);
90+
91+
protected abstract boolean valiateFilename(Path file);
92+
}

hbase-server/src/main/java/org/apache/hadoop/hbase/master/cleaner/HFileCleaner.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.hadoop.hbase.Stoppable;
3333
import org.apache.hadoop.hbase.conf.ConfigurationObserver;
3434
import org.apache.hadoop.hbase.io.HFileLink;
35+
import org.apache.hadoop.hbase.master.store.LocalStore;
3536
import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
3637
import org.apache.hadoop.hbase.util.StealJobQueue;
3738
import org.apache.yetus.audience.InterfaceAudience;
@@ -158,10 +159,9 @@ public HFileCleaner(String name, int period, Stoppable stopper, Configuration co
158159

159160
@Override
160161
protected boolean validate(Path file) {
161-
if (HFileLink.isBackReferencesDir(file) || HFileLink.isBackReferencesDir(file.getParent())) {
162-
return true;
163-
}
164-
return StoreFileInfo.validateStoreFileName(file.getName());
162+
return HFileLink.isBackReferencesDir(file) || HFileLink.isBackReferencesDir(file.getParent()) ||
163+
StoreFileInfo.validateStoreFileName(file.getName()) ||
164+
file.getName().endsWith(LocalStore.ARCHIVED_HFILE_SUFFIX);
165165
}
166166

167167
/**

hbase-server/src/main/java/org/apache/hadoop/hbase/master/cleaner/LogCleaner.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.hadoop.hbase.Stoppable;
3636
import org.apache.hadoop.hbase.conf.ConfigurationObserver;
3737
import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil;
38+
import org.apache.hadoop.hbase.master.store.LocalStore;
3839
import org.apache.hadoop.hbase.wal.AbstractFSWALProvider;
3940
import org.apache.yetus.audience.InterfaceAudience;
4041
import org.slf4j.Logger;
@@ -86,8 +87,9 @@ public LogCleaner(final int period, final Stoppable stopper, Configuration conf,
8687

8788
@Override
8889
protected boolean validate(Path file) {
89-
return AbstractFSWALProvider.validateWALFilename(file.getName())
90-
|| MasterProcedureUtil.validateProcedureWALFilename(file.getName());
90+
return AbstractFSWALProvider.validateWALFilename(file.getName()) ||
91+
MasterProcedureUtil.validateProcedureWALFilename(file.getName()) ||
92+
file.getName().endsWith(LocalStore.ARCHIVED_WAL_SUFFIX);
9193
}
9294

9395
@Override

hbase-server/src/main/java/org/apache/hadoop/hbase/master/cleaner/TimeToLiveHFileCleaner.java

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,33 @@
1717
*/
1818
package org.apache.hadoop.hbase.master.cleaner;
1919

20-
import org.apache.yetus.audience.InterfaceAudience;
21-
import org.slf4j.Logger;
22-
import org.slf4j.LoggerFactory;
2320
import org.apache.hadoop.conf.Configuration;
24-
import org.apache.hadoop.fs.FileStatus;
21+
import org.apache.hadoop.fs.Path;
2522
import org.apache.hadoop.hbase.HBaseInterfaceAudience;
26-
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
23+
import org.apache.hadoop.hbase.io.HFileLink;
24+
import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
25+
import org.apache.yetus.audience.InterfaceAudience;
2726

2827
/**
2928
* HFile cleaner that uses the timestamp of the hfile to determine if it should be deleted. By
3029
* default they are allowed to live for {@value #DEFAULT_TTL}
3130
*/
3231
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
33-
public class TimeToLiveHFileCleaner extends BaseHFileCleanerDelegate {
32+
public class TimeToLiveHFileCleaner extends BaseTimeToLiveFileCleaner {
3433

35-
private static final Logger LOG = LoggerFactory.getLogger(TimeToLiveHFileCleaner.class.getName());
3634
public static final String TTL_CONF_KEY = "hbase.master.hfilecleaner.ttl";
35+
3736
// default ttl = 5 minutes
3837
public static final long DEFAULT_TTL = 60000 * 5;
39-
// Configured time a hfile can be kept after it was moved to the archive
40-
private long ttl;
4138

4239
@Override
43-
public void setConf(Configuration conf) {
44-
this.ttl = conf.getLong(TTL_CONF_KEY, DEFAULT_TTL);
45-
super.setConf(conf);
40+
protected long getTtlMs(Configuration conf) {
41+
return conf.getLong(TTL_CONF_KEY, DEFAULT_TTL);
4642
}
4743

4844
@Override
49-
public boolean isFileDeletable(FileStatus fStat) {
50-
long currentTime = EnvironmentEdgeManager.currentTime();
51-
long time = fStat.getModificationTime();
52-
long life = currentTime - time;
53-
if (LOG.isTraceEnabled()) {
54-
LOG.trace("HFile life:" + life + ", ttl:" + ttl + ", current:" + currentTime + ", from: "
55-
+ time);
56-
}
57-
if (life < 0) {
58-
LOG.warn("Found a hfile (" + fStat.getPath() + ") newer than current time (" + currentTime
59-
+ " < " + time + "), probably a clock skew");
60-
return false;
61-
}
62-
return life > ttl;
45+
protected boolean valiateFilename(Path file) {
46+
return HFileLink.isBackReferencesDir(file) || HFileLink.isBackReferencesDir(file.getParent()) ||
47+
StoreFileInfo.validateStoreFileName(file.getName());
6348
}
6449
}

0 commit comments

Comments
 (0)