HBASE-25899 Improve efficiency of SnapshotHFileCleaner (#3280)
Signed-off-by: Duo Zhang <zhangduo@apache.org>
This commit is contained in:
parent
f94f4e29fe
commit
b02c8102b7
|
@ -20,10 +20,8 @@ package org.apache.hadoop.hbase.master.snapshot;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
|
@ -36,6 +34,8 @@ import org.apache.hadoop.hbase.Stoppable;
|
||||||
import org.apache.hadoop.hbase.snapshot.CorruptedSnapshotException;
|
import org.apache.hadoop.hbase.snapshot.CorruptedSnapshotException;
|
||||||
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
|
import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
|
||||||
import org.apache.hadoop.hbase.util.CommonFSUtils;
|
import org.apache.hadoop.hbase.util.CommonFSUtils;
|
||||||
|
import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableMap;
|
||||||
|
import org.apache.hbase.thirdparty.com.google.common.collect.ImmutableSet;
|
||||||
import org.apache.yetus.audience.InterfaceAudience;
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
import org.apache.yetus.audience.InterfaceStability;
|
import org.apache.yetus.audience.InterfaceStability;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -91,12 +91,12 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
private final FileSystem fs, workingFs;
|
private final FileSystem fs, workingFs;
|
||||||
private final SnapshotFileInspector fileInspector;
|
private final SnapshotFileInspector fileInspector;
|
||||||
private final Path snapshotDir, workingSnapshotDir;
|
private final Path snapshotDir, workingSnapshotDir;
|
||||||
private final Set<String> cache = new HashSet<>();
|
private volatile ImmutableSet<String> cache = ImmutableSet.of();
|
||||||
/**
|
/**
|
||||||
* This is a helper map of information about the snapshot directories so we don't need to rescan
|
* This is a helper map of information about the snapshot directories so we don't need to rescan
|
||||||
* them if they haven't changed since the last time we looked.
|
* them if they haven't changed since the last time we looked.
|
||||||
*/
|
*/
|
||||||
private final Map<String, SnapshotDirectoryInfo> snapshots = new HashMap<>();
|
private ImmutableMap<String, SnapshotDirectoryInfo> snapshots = ImmutableMap.of();
|
||||||
private final Timer refreshTimer;
|
private final Timer refreshTimer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,7 +184,7 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
// XXX this is inefficient to synchronize on the method, when what we really need to guard against
|
// XXX this is inefficient to synchronize on the method, when what we really need to guard against
|
||||||
// is an illegal access to the cache. Really we could do a mutex-guarded pointer swap on the
|
// is an illegal access to the cache. Really we could do a mutex-guarded pointer swap on the
|
||||||
// cache, but that seems overkill at the moment and isn't necessarily a bottleneck.
|
// cache, but that seems overkill at the moment and isn't necessarily a bottleneck.
|
||||||
public synchronized Iterable<FileStatus> getUnreferencedFiles(Iterable<FileStatus> files,
|
public Iterable<FileStatus> getUnreferencedFiles(Iterable<FileStatus> files,
|
||||||
final SnapshotManager snapshotManager) throws IOException {
|
final SnapshotManager snapshotManager) throws IOException {
|
||||||
List<FileStatus> unReferencedFiles = Lists.newArrayList();
|
List<FileStatus> unReferencedFiles = Lists.newArrayList();
|
||||||
List<String> snapshotsInProgress = null;
|
List<String> snapshotsInProgress = null;
|
||||||
|
@ -200,13 +200,17 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
"skip to clean the HFiles this time");
|
"skip to clean the HFiles this time");
|
||||||
return unReferencedFiles;
|
return unReferencedFiles;
|
||||||
}
|
}
|
||||||
|
ImmutableSet<String> currentCache = cache;
|
||||||
for (FileStatus file : files) {
|
for (FileStatus file : files) {
|
||||||
String fileName = file.getPath().getName();
|
String fileName = file.getPath().getName();
|
||||||
if (!refreshed && !cache.contains(fileName)) {
|
if (!refreshed && !currentCache.contains(fileName)) {
|
||||||
|
synchronized (this) {
|
||||||
refreshCache();
|
refreshCache();
|
||||||
|
currentCache = cache;
|
||||||
refreshed = true;
|
refreshed = true;
|
||||||
}
|
}
|
||||||
if (cache.contains(fileName)) {
|
}
|
||||||
|
if (currentCache.contains(fileName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (snapshotsInProgress == null) {
|
if (snapshotsInProgress == null) {
|
||||||
|
@ -235,22 +239,23 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
|
|
||||||
// clear the cache, as in the below code, either we will also clear the snapshots, or we will
|
// clear the cache, as in the below code, either we will also clear the snapshots, or we will
|
||||||
// refill the file name cache again.
|
// refill the file name cache again.
|
||||||
this.cache.clear();
|
|
||||||
if (ArrayUtils.isEmpty(snapshotDirs)) {
|
if (ArrayUtils.isEmpty(snapshotDirs)) {
|
||||||
// remove all the remembered snapshots because we don't have any left
|
// remove all the remembered snapshots because we don't have any left
|
||||||
if (LOG.isDebugEnabled() && this.snapshots.size() > 0) {
|
if (LOG.isDebugEnabled() && this.snapshots.size() > 0) {
|
||||||
LOG.debug("No snapshots on-disk, clear cache");
|
LOG.debug("No snapshots on-disk, clear cache");
|
||||||
}
|
}
|
||||||
this.snapshots.clear();
|
this.snapshots = ImmutableMap.of();
|
||||||
|
this.cache = ImmutableSet.of();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImmutableSet.Builder<String> cacheBuilder = ImmutableSet.builder();
|
||||||
|
ImmutableMap.Builder<String, SnapshotDirectoryInfo> snapshotsBuilder = ImmutableMap.builder();
|
||||||
// iterate over all the cached snapshots and see if we need to update some, it is not an
|
// iterate over all the cached snapshots and see if we need to update some, it is not an
|
||||||
// expensive operation if we do not reload the manifest of snapshots.
|
// expensive operation if we do not reload the manifest of snapshots.
|
||||||
Map<String, SnapshotDirectoryInfo> newSnapshots = new HashMap<>();
|
|
||||||
for (FileStatus snapshotDir : snapshotDirs) {
|
for (FileStatus snapshotDir : snapshotDirs) {
|
||||||
String name = snapshotDir.getPath().getName();
|
String name = snapshotDir.getPath().getName();
|
||||||
SnapshotDirectoryInfo files = this.snapshots.remove(name);
|
SnapshotDirectoryInfo files = snapshots.get(name);
|
||||||
// if we don't know about the snapshot or its been modified, we need to update the
|
// if we don't know about the snapshot or its been modified, we need to update the
|
||||||
// files the latter could occur where I create a snapshot, then delete it, and then make a
|
// files the latter could occur where I create a snapshot, then delete it, and then make a
|
||||||
// new snapshot with the same name. We will need to update the cache the information from
|
// new snapshot with the same name. We will need to update the cache the information from
|
||||||
|
@ -262,19 +267,20 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
files = new SnapshotDirectoryInfo(snapshotDir.getModificationTime(), storedFiles);
|
files = new SnapshotDirectoryInfo(snapshotDir.getModificationTime(), storedFiles);
|
||||||
}
|
}
|
||||||
// add all the files to cache
|
// add all the files to cache
|
||||||
this.cache.addAll(files.getFiles());
|
cacheBuilder.addAll(files.getFiles());
|
||||||
newSnapshots.put(name, files);
|
snapshotsBuilder.put(name, files);
|
||||||
}
|
}
|
||||||
// set the snapshots we are tracking
|
// set the snapshots we are tracking
|
||||||
this.snapshots.clear();
|
this.snapshots = snapshotsBuilder.build();
|
||||||
this.snapshots.putAll(newSnapshots);
|
this.cache = cacheBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> getSnapshotsInProgress() throws IOException {
|
List<String> getSnapshotsInProgress() throws IOException {
|
||||||
List<String> snapshotInProgress = Lists.newArrayList();
|
List<String> snapshotInProgress = Lists.newArrayList();
|
||||||
// only add those files to the cache, but not to the known snapshots
|
// only add those files to the cache, but not to the known snapshots
|
||||||
|
|
||||||
FileStatus[] snapshotsInProgress = CommonFSUtils.listStatus(this.workingFs, this.workingSnapshotDir);
|
FileStatus[] snapshotsInProgress = CommonFSUtils.listStatus(this.workingFs,
|
||||||
|
this.workingSnapshotDir);
|
||||||
|
|
||||||
if (!ArrayUtils.isEmpty(snapshotsInProgress)) {
|
if (!ArrayUtils.isEmpty(snapshotsInProgress)) {
|
||||||
for (FileStatus snapshot : snapshotsInProgress) {
|
for (FileStatus snapshot : snapshotsInProgress) {
|
||||||
|
@ -301,11 +307,10 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.warn("Failed to refresh snapshot hfile cache!", e);
|
LOG.warn("Failed to refresh snapshot hfile cache!", e);
|
||||||
// clear all the cached entries if we meet an error
|
// clear all the cached entries if we meet an error
|
||||||
cache.clear();
|
cache = ImmutableSet.of();
|
||||||
snapshots.clear();
|
snapshots = ImmutableMap.of();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +320,6 @@ public class SnapshotFileCache implements Stoppable {
|
||||||
this.stop = true;
|
this.stop = true;
|
||||||
this.refreshTimer.cancel();
|
this.refreshTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class SnapshotHFileCleaner extends BaseHFileCleanerDelegate {
|
||||||
private MasterServices master;
|
private MasterServices master;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Iterable<FileStatus> getDeletableFiles(Iterable<FileStatus> files) {
|
public Iterable<FileStatus> getDeletableFiles(Iterable<FileStatus> files) {
|
||||||
try {
|
try {
|
||||||
return cache.getUnreferencedFiles(files, master.getSnapshotManager());
|
return cache.getUnreferencedFiles(files, master.getSnapshotManager());
|
||||||
} catch (CorruptedSnapshotException cse) {
|
} catch (CorruptedSnapshotException cse) {
|
||||||
|
|
Loading…
Reference in New Issue