Added StorageMigrationType and cli commands

This commit is contained in:
Josh Slocum 2021-09-07 18:26:43 -05:00
parent 0fd4cc14d7
commit 9992a7b33f
11 changed files with 144 additions and 8 deletions

View File

@ -64,7 +64,7 @@ The ``commit`` command commits the current transaction. Any sets or clears execu
configure
---------
The ``configure`` command changes the database configuration. Its syntax is ``configure [new|tss] [single|double|triple|three_data_hall|three_datacenter] [ssd|memory] [grv_proxies=<N>] [commit_proxies=<N>] [resolvers=<N>] [logs=<N>] [count=<TSS_COUNT>] [perpetual_storage_wiggle=<WIGGLE_SPEED>]``.
The ``configure`` command changes the database configuration. Its syntax is ``configure [new|tss] [single|double|triple|three_data_hall|three_datacenter] [ssd|memory] [grv_proxies=<N>] [commit_proxies=<N>] [resolvers=<N>] [logs=<N>] [count=<TSS_COUNT>] [perpetual_storage_wiggle=<WIGGLE_SPEED>] [storage_migration_type={disabled|aggressive|gradual}]``.
The ``new`` option, if present, initializes a new database with the given configuration rather than changing the configuration of an existing one. When ``new`` is used, both a redundancy mode and a storage engine must be specified.
@ -114,6 +114,20 @@ perpetual storage wiggle
Set the value speed (a.k.a., the number of processes that the Data Distributor should wiggle at a time). Currently, only 0 and 1 are supported. The value 0 means to disable the perpetual storage wiggle. For more details, see :ref:`perpetual-storage-wiggle`.
storage migration type
^^^^^^^^^^^^^^^^^^^^^^
Set the storage migration type, or how FDB should migrate to a new storage engine if the value is changed.
The default is ``disabled``.
* ``disabled``
* ``gradual``
* ``aggressive``
``gradual`` replaces a single storage at a time when the ``perpetual storage wiggle`` is active. This requires the perpetual storage wiggle to be set to a non-zero value to actually migrate storage servers. It is somewhat slow but very safe.
``aggressive`` tries to replace as many storages as it can at once, and will recruit a new storage server on the same process as the old one. The main benefit over ``gradual`` is that this doesn't need to take one storage out of rotation, so it works for small or development clusters that have the same number of storage processes as the replication factor.
consistencycheck
----------------

View File

@ -735,7 +735,13 @@
"grv_proxies":1, // this field will be absent if a value has not been explicitly set
"proxies":6, // this field will be absent if a value has not been explicitly set
"backup_worker_enabled":1,
"perpetual_storage_wiggle": 0
"perpetual_storage_wiggle": 0,
"storage_migration_type":{
"$enum":[
"disabled",
"gradual",
"aggressive"
]}
},
"data":{
"least_operating_space_bytes_log_server":0,

View File

@ -31,6 +31,8 @@ Configuration
You can configure the Perpetual Storage Wiggle via the FDB :ref:`command line interface <command-line-interface>`.
Note that to have the Perpetual Storage Wiggle change the storage engine type, you must configure ``storage_migration_type=gradual``.
Example commands
----------------

View File

@ -473,7 +473,8 @@ void initHelp() {
"configure [new|tss]"
"<single|double|triple|three_data_hall|three_datacenter|ssd|memory|memory-radixtree-beta|proxies=<PROXIES>|"
"commit_proxies=<COMMIT_PROXIES>|grv_proxies=<GRV_PROXIES>|logs=<LOGS>|resolvers=<RESOLVERS>>*|"
"count=<TSS_COUNT>|perpetual_storage_wiggle=<WIGGLE_SPEED>",
"count=<TSS_COUNT>|perpetual_storage_wiggle=<WIGGLE_SPEED>|storage_migration_type={disabled|gradual|"
"aggressive}",
"change the database configuration",
"The `new' option, if present, initializes a new database with the given configuration rather than changing "
"the configuration of an existing one. When used, both a redundancy mode and a storage engine must be "
@ -882,6 +883,27 @@ ACTOR Future<bool> configure(Database db,
break;
case ConfigurationResult::LOCKED_NOT_NEW:
fprintf(stderr, "ERROR: `only new databases can be configured as locked`\n");
ret = false;
break;
case ConfigurationResult::SUCCESS_WARN_PPW_GRADUAL:
printf("Configuration changed, with warnings\n");
fprintf(stderr,
"WARN: To make progress toward the desired storage type with storage_migration_type=gradual, the "
"Perpetual Wiggle must be enabled.\n");
fprintf(stderr,
"Type `configure perpetual_storage_wiggle=1' to enable the perpetual wiggle, or `configure "
"storage_migration_type=gradual' to set the gradual migration type.\n");
ret = true;
break;
case ConfigurationResult::SUCCESS_WARN_CHANGE_STORAGE_NOMIGRATE:
printf("Configuration changed, with warnings\n");
fprintf(stderr,
"WARN: Storage engine type changed, but nothing will be migrated because "
"storage_migration_mode=disabled.\n");
fprintf(stderr,
"Type `configure perpetual_storage_wiggle=1 storage_migration_type=gradual' to enable gradual "
"migration with the perpetual wiggle, or `configure "
"storage_migration_type=aggressive' for aggressive migration.\n");
ret = true;
break;
default:
@ -1566,6 +1588,7 @@ void configureGenerator(const char* text, const char* line, std::vector<std::str
"logs=",
"resolvers=",
"perpetual_storage_wiggle=",
"storage_migration_type=",
nullptr };
arrayGenerator(text, line, opts, lc);
}

View File

@ -45,6 +45,7 @@ void DatabaseConfiguration::resetInternal() {
remoteTLogReplicationFactor = repopulateRegionAntiQuorum = 0;
backupWorkerEnabled = false;
perpetualStorageWiggleSpeed = 0;
storageMigrationType = StorageMigrationType::DEFAULT;
}
void parse(int* i, ValueRef const& v) {
@ -198,7 +199,8 @@ bool DatabaseConfiguration::isValid() const {
(usableRegions == 1 || regions.size() == 2) && (regions.size() == 0 || regions[0].priority >= 0) &&
(regions.size() == 0 || tLogPolicy->info() != "dcid^2 x zoneid^2 x 1") &&
// We cannot specify regions with three_datacenter replication
(perpetualStorageWiggleSpeed == 0 || perpetualStorageWiggleSpeed == 1))) {
(perpetualStorageWiggleSpeed == 0 || perpetualStorageWiggleSpeed == 1)) &&
storageMigrationType != StorageMigrationType::UNSET) {
return false;
}
std::set<Key> dcIds;
@ -389,6 +391,7 @@ StatusObject DatabaseConfiguration::toJSON(bool noPolicies) const {
result["backup_worker_enabled"] = (int32_t)backupWorkerEnabled;
result["perpetual_storage_wiggle"] = perpetualStorageWiggleSpeed;
result["storage_migration_type"] = storageMigrationType.toString();
return result;
}
@ -542,6 +545,9 @@ bool DatabaseConfiguration::setInternal(KeyRef key, ValueRef value) {
parse(&regions, value);
} else if (ck == LiteralStringRef("perpetual_storage_wiggle")) {
parse(&perpetualStorageWiggleSpeed, value);
} else if (ck == LiteralStringRef("storage_migration_type")) {
parse((&type), value);
storageMigrationType = (StorageMigrationType::MigrationType)type;
} else {
return false;
}

View File

@ -246,6 +246,9 @@ struct DatabaseConfiguration {
// Perpetual Storage Setting
int32_t perpetualStorageWiggleSpeed;
// Storage Migration Type
StorageMigrationType storageMigrationType;
// Excluded servers (no state should be here)
bool isExcludedServer(NetworkAddressList) const;
bool isExcludedLocality(const LocalityData& locality) const;

View File

@ -1126,4 +1126,41 @@ inline const char* transactionPriorityToString(TransactionPriority priority, boo
throw internal_error();
}
struct StorageMigrationType {
// These enumerated values are stored in the database configuration, so can NEVER be changed. Only add new ones
// just before END.
enum MigrationType { DEFAULT = 1, UNSET = 0, DISABLED = 1, AGGRESSIVE = 2, GRADUAL = 3, END = 4 };
StorageMigrationType() : type(UNSET) {}
StorageMigrationType(MigrationType type) : type(type) {
if ((uint32_t)type >= END) {
this->type = UNSET;
}
}
operator MigrationType() const { return MigrationType(type); }
template <class Ar>
void serialize(Ar& ar) {
serializer(ar, type);
}
std::string toString() const {
switch (type) {
case DISABLED:
return "disabled";
case AGGRESSIVE:
return "aggressive";
case GRADUAL:
return "gradual";
case UNSET:
return "unset";
default:
ASSERT(false);
}
return "";
}
uint32_t type;
};
#endif

View File

@ -150,6 +150,20 @@ std::map<std::string, std::string> configForToken(std::string const& mode) {
}
out[p + key] = value;
}
if (key == "storage_migration_type") {
StorageMigrationType type;
if (value == "disabled") {
type = StorageMigrationType::DISABLED;
} else if (value == "aggressive") {
type = StorageMigrationType::AGGRESSIVE;
} else if (value == "gradual") {
type = StorageMigrationType::GRADUAL;
} else {
printf("Error: Only disabled|aggressive|gradual are valid for storage_migration_mode.\n");
return out;
}
out[p + key] = format("%d", type);
}
return out;
}
@ -445,6 +459,8 @@ ACTOR Future<ConfigurationResult> changeConfig(Database cx, std::map<std::string
state Future<Void> tooLong = delay(60);
state Key versionKey = BinaryWriter::toValue(deterministicRandom()->randomUniqueID(), Unversioned());
state bool oldReplicationUsesDcId = false;
state bool warnPPWGradual = false;
state bool warnChangeStorageNoMigrate = false;
loop {
try {
tr.setOption(FDBTransactionOptions::PRIORITY_SYSTEM_IMMEDIATE);
@ -615,6 +631,16 @@ ACTOR Future<ConfigurationResult> changeConfig(Database cx, std::map<std::string
return ConfigurationResult::NOT_ENOUGH_WORKERS;
}
}
if (newConfig.storageServerStoreType != oldConfig.storageServerStoreType &&
newConfig.storageMigrationType == StorageMigrationType::DISABLED) {
warnChangeStorageNoMigrate = true;
} else if ((newConfig.storageMigrationType == StorageMigrationType::GRADUAL &&
newConfig.perpetualStorageWiggleSpeed == 0) ||
(newConfig.perpetualStorageWiggleSpeed > 0 &&
newConfig.storageMigrationType == StorageMigrationType::DISABLED)) {
warnPPWGradual = true;
}
}
}
if (creating) {
@ -670,7 +696,14 @@ ACTOR Future<ConfigurationResult> changeConfig(Database cx, std::map<std::string
wait(tr.onError(e1));
}
}
return ConfigurationResult::SUCCESS;
if (warnPPWGradual) {
return ConfigurationResult::SUCCESS_WARN_PPW_GRADUAL;
} else if (warnChangeStorageNoMigrate) {
return ConfigurationResult::SUCCESS_WARN_CHANGE_STORAGE_NOMIGRATE;
} else {
return ConfigurationResult::SUCCESS;
}
}
ConfigureAutoResult parseConfig(StatusObject const& status) {

View File

@ -60,6 +60,8 @@ enum class ConfigurationResult {
REGION_REPLICATION_MISMATCH,
DCID_MISSING,
LOCKED_NOT_NEW,
SUCCESS_WARN_PPW_GRADUAL,
SUCCESS_WARN_CHANGE_STORAGE_NOMIGRATE,
SUCCESS,
};

View File

@ -759,7 +759,13 @@ const KeyRef JSONSchemas::statusSchema = LiteralStringRef(R"statusSchema(
"grv_proxies":1,
"proxies":6,
"backup_worker_enabled":1,
"perpetual_storage_wiggle":0
"perpetual_storage_wiggle":0,
"storage_migration_type": {
"$enum":[
"disabled",
"aggressive",
"gradual"
]}
},
"data":{
"least_operating_space_bytes_log_server":0,

View File

@ -1242,7 +1242,7 @@ void SimulationConfig::setRandomConfig() {
set_config("perpetual_storage_wiggle=0");
} else {
// TraceEvent("SimulatedConfigRandom").detail("PerpetualWiggle", 1);
set_config("perpetual_storage_wiggle=1");
set_config("storage_migration_type=gradual perpetual_storage_wiggle=1");
}
if (deterministicRandom()->random01() < 0.5) {
@ -1779,7 +1779,11 @@ void setupSimulatedSystem(vector<Future<Void>>* systemActors,
if (kv.second.type() == json_spirit::int_type) {
startingConfigString += kv.first + ":=" + format("%d", kv.second.get_int());
} else if (kv.second.type() == json_spirit::str_type) {
startingConfigString += kv.second.get_str();
if ("storage_migration_type" == kv.first) {
startingConfigString += kv.first + "=" + kv.second.get_str();
} else {
startingConfigString += kv.second.get_str();
}
} else if (kv.second.type() == json_spirit::array_type) {
startingConfigString += kv.first + "=" +
json_spirit::write_string(json_spirit::mValue(kv.second.get_array()),