Add an option for fast restore to restore old backups

If "usePartitionedLogs" is set to false, then the workload uses old backups for
restore.
This commit is contained in:
Jingyu Zhou 2020-03-25 22:53:22 -07:00
parent 1052b23ee1
commit 772ab70aee
4 changed files with 34 additions and 9 deletions

View File

@ -657,6 +657,18 @@ public:
return dumpFileList_impl(Reference<BackupContainerFileSystem>::addRef(this), begin, end); return dumpFileList_impl(Reference<BackupContainerFileSystem>::addRef(this), begin, end);
} }
ACTOR static Future<bool> isPartitionedBackup_impl(Reference<BackupContainerFileSystem> bc) {
BackupFileList list = wait(bc->dumpFileList(0, std::numeric_limits<Version>::max()));
for (const auto& file : list.logs) {
if (file.isPartitionedLog()) return true;
}
return false;
}
Future<bool> isPartitionedBackup() final {
return isPartitionedBackup_impl(Reference<BackupContainerFileSystem>::addRef(this));
}
static Version resolveRelativeVersion(Optional<Version> max, Version v, const char *name, Error e) { static Version resolveRelativeVersion(Optional<Version> max, Version v, const char *name, Error e) {
if(v == invalidVersion) { if(v == invalidVersion) {
TraceEvent(SevError, "BackupExpireInvalidVersion").detail(name, v); TraceEvent(SevError, "BackupExpireInvalidVersion").detail(name, v);

View File

@ -88,6 +88,10 @@ struct LogFile {
return beginVersion >= rhs.beginVersion && endVersion <= rhs.endVersion && tagId == rhs.tagId; return beginVersion >= rhs.beginVersion && endVersion <= rhs.endVersion && tagId == rhs.tagId;
} }
bool isPartitionedLog() const {
return tagId >= 0 && tagId < totalTags;
}
std::string toString() const { std::string toString() const {
std::stringstream ss; std::stringstream ss;
ss << "beginVersion:" << std::to_string(beginVersion) << " endVersion:" << std::to_string(endVersion) ss << "beginVersion:" << std::to_string(beginVersion) << " endVersion:" << std::to_string(endVersion)
@ -261,6 +265,9 @@ public:
virtual Future<BackupFileList> dumpFileList(Version begin = 0, Version end = std::numeric_limits<Version>::max()) = 0; virtual Future<BackupFileList> dumpFileList(Version begin = 0, Version end = std::numeric_limits<Version>::max()) = 0;
// If there are partitioned log files, then returns true; otherwise, returns false.
virtual Future<bool> isPartitionedBackup() = 0;
// Get exactly the files necessary to restore to targetVersion. Returns non-present if // Get exactly the files necessary to restore to targetVersion. Returns non-present if
// restore to given version is not possible. // restore to given version is not possible.
virtual Future<Optional<RestorableFileSet>> getRestoreSet(Version targetVersion) = 0; virtual Future<Optional<RestorableFileSet>> getRestoreSet(Version targetVersion) = 0;

View File

@ -641,7 +641,8 @@ ACTOR static Future<Standalone<VectorRef<RestoreRequest>>> collectRestoreRequest
ACTOR static Future<Version> collectBackupFiles(Reference<IBackupContainer> bc, std::vector<RestoreFileFR>* rangeFiles, ACTOR static Future<Version> collectBackupFiles(Reference<IBackupContainer> bc, std::vector<RestoreFileFR>* rangeFiles,
std::vector<RestoreFileFR>* logFiles, Database cx, std::vector<RestoreFileFR>* logFiles, Database cx,
RestoreRequest request) { RestoreRequest request) {
state BackupDescription desc = wait(bc->describePartitionedBackup()); state bool partitioned = wait(bc->isPartitionedBackup());
state BackupDescription desc = wait(partitioned ? bc->describePartitionedBackup() : bc->describeBackup());
// Convert version to real time for operators to read the BackupDescription desc. // Convert version to real time for operators to read the BackupDescription desc.
wait(desc.resolveVersionTimes(cx)); wait(desc.resolveVersionTimes(cx));
@ -657,9 +658,8 @@ ACTOR static Future<Version> collectBackupFiles(Reference<IBackupContainer> bc,
std::cout << "Restore to version: " << request.targetVersion << "\nBackupDesc: \n" << desc.toString() << "\n\n"; std::cout << "Restore to version: " << request.targetVersion << "\nBackupDesc: \n" << desc.toString() << "\n\n";
} }
Optional<RestorableFileSet> restorable = Optional<RestorableFileSet> restorable = wait(partitioned ? bc->getPartitionedRestoreSet(request.targetVersion)
wait(SERVER_KNOBS->FASTRESTORE_USE_PARTITIONED_LOGS ? bc->getPartitionedRestoreSet(request.targetVersion) : bc->getRestoreSet(request.targetVersion));
: bc->getRestoreSet(request.targetVersion));
if (!restorable.present()) { if (!restorable.present()) {
TraceEvent(SevWarn, "FastRestoreMasterPhaseCollectBackupFiles").detail("NotRestorable", request.targetVersion); TraceEvent(SevWarn, "FastRestoreMasterPhaseCollectBackupFiles").detail("NotRestorable", request.targetVersion);

View File

@ -21,6 +21,7 @@
#include "fdbrpc/simulator.h" #include "fdbrpc/simulator.h"
#include "fdbclient/BackupAgent.actor.h" #include "fdbclient/BackupAgent.actor.h"
#include "fdbclient/BackupContainer.h" #include "fdbclient/BackupContainer.h"
#include "fdbserver/Knobs.h"
#include "fdbserver/workloads/workloads.actor.h" #include "fdbserver/workloads/workloads.actor.h"
#include "fdbserver/workloads/BulkSetup.actor.h" #include "fdbserver/workloads/BulkSetup.actor.h"
#include "fdbclient/RestoreWorkerInterface.actor.h" #include "fdbclient/RestoreWorkerInterface.actor.h"
@ -40,6 +41,7 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
bool locked; bool locked;
bool allowPauses; bool allowPauses;
bool shareLogRange; bool shareLogRange;
bool usePartitionedLogs;
std::map<Standalone<KeyRef>, Standalone<ValueRef>> dbKVs; std::map<Standalone<KeyRef>, Standalone<ValueRef>> dbKVs;
@ -67,6 +69,7 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
agentRequest = getOption(options, LiteralStringRef("simBackupAgents"), true); agentRequest = getOption(options, LiteralStringRef("simBackupAgents"), true);
allowPauses = getOption(options, LiteralStringRef("allowPauses"), true); allowPauses = getOption(options, LiteralStringRef("allowPauses"), true);
shareLogRange = getOption(options, LiteralStringRef("shareLogRange"), false); shareLogRange = getOption(options, LiteralStringRef("shareLogRange"), false);
usePartitionedLogs = getOption(options, LiteralStringRef("usePartitionedLogs"), true);
KeyRef beginRange; KeyRef beginRange;
KeyRef endRange; KeyRef endRange;
@ -181,7 +184,7 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
try { try {
wait(backupAgent->submitBackup(cx, StringRef(backupContainer), deterministicRandom()->randomInt(0, 100), wait(backupAgent->submitBackup(cx, StringRef(backupContainer), deterministicRandom()->randomInt(0, 100),
tag.toString(), backupRanges, stopDifferentialDelay ? false : true, tag.toString(), backupRanges, stopDifferentialDelay ? false : true,
/*partitionedLog=*/true)); /*partitionedLog=*/self->usePartitionedLogs));
} catch (Error& e) { } catch (Error& e) {
TraceEvent("BARW_DoBackupSubmitBackupException", randomID).error(e).detail("Tag", printable(tag)); TraceEvent("BARW_DoBackupSubmitBackupException", randomID).error(e).detail("Tag", printable(tag));
if (e.code() != error_code_backup_unneeded && e.code() != error_code_backup_duplicate) throw; if (e.code() != error_code_backup_unneeded && e.code() != error_code_backup_duplicate) throw;
@ -209,8 +212,10 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
TraceEvent("BARW_DoBackupWaitForRestorable", randomID).detail("Tag", backupTag.tagName).detail("Result", resultWait); TraceEvent("BARW_DoBackupWaitForRestorable", randomID).detail("Tag", backupTag.tagName).detail("Result", resultWait);
state bool restorable = false; state bool restorable = false;
if(lastBackupContainer) { if (lastBackupContainer) {
state Future<BackupDescription> fdesc = lastBackupContainer->describePartitionedBackup(); state Future<BackupDescription> fdesc = self->usePartitionedLogs
? lastBackupContainer->describePartitionedBackup()
: lastBackupContainer->describeBackup();
wait(ready(fdesc)); wait(ready(fdesc));
if(!fdesc.isError()) { if(!fdesc.isError()) {
@ -398,7 +403,7 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
try { try {
extraBackup = backupAgent.submitBackup( extraBackup = backupAgent.submitBackup(
cx, LiteralStringRef("file://simfdb/backups/"), deterministicRandom()->randomInt(0, 100), cx, LiteralStringRef("file://simfdb/backups/"), deterministicRandom()->randomInt(0, 100),
self->backupTag.toString(), self->backupRanges, true, /*partitionedLog=*/true); self->backupTag.toString(), self->backupRanges, true, self->usePartitionedLogs);
} catch (Error& e) { } catch (Error& e) {
TraceEvent("BARW_SubmitBackup2Exception", randomID) TraceEvent("BARW_SubmitBackup2Exception", randomID)
.error(e) .error(e)
@ -431,7 +436,8 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload {
.detail("BackupTag", printable(self->backupTag)); .detail("BackupTag", printable(self->backupTag));
auto container = IBackupContainer::openContainer(lastBackupContainer->getURL()); auto container = IBackupContainer::openContainer(lastBackupContainer->getURL());
BackupDescription desc = wait(container->describePartitionedBackup()); BackupDescription desc = wait(self->usePartitionedLogs ? container->describePartitionedBackup()
: container->describeBackup());
state Version targetVersion = -1; state Version targetVersion = -1;
if (desc.maxRestorableVersion.present()) { if (desc.maxRestorableVersion.present()) {