Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add the ability to checkpoint an existing server, and spawn a read-only server on that view. #2548

Open
wants to merge 21 commits into
base: unstable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions kvrocks.conf
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ db-name change.me.db
# Note that you must specify a directory here, not a file name.
dir /tmp/kvrocks

# Optional: A snapshot directory
#
# If specified, Kvrocks will snapshot the DB at [dir] to the specified [snapshot-dir],
# and start a read-only server from the snapshot.
#
# snapshot-dir /tmp/kvrocks-snapshot-changeme

# You can configure where to store your server logs by the log-dir.
# If you don't specify one, we will use the above `dir` as our default log directory.
# We also can send logs to stdout/stderr is as simple as:
Expand Down
3 changes: 2 additions & 1 deletion src/cli/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ int main(int argc, char *argv[]) {
#endif

engine::Storage storage(&config);
s = storage.Open();
s = storage.Open(kDBOpenModeDefault);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I think we don't need to change it?


if (!s.IsOK()) {
LOG(ERROR) << "Failed to open: " << s.Msg();
return 1;
Expand Down
3 changes: 1 addition & 2 deletions src/config/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@
#include <rocksdb/env.h>
#include <strings.h>

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <limits>
#include <string>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -190,6 +188,7 @@ Config::Config() {
new IntField(&force_compact_file_min_deleted_percentage, 10, 1, 100)},
{"db-name", true, new StringField(&db_name, "change.me.db")},
{"dir", true, new StringField(&dir, kDefaultDir)},
{"snapshot-dir", true, new StringField(&snapshot_dir, "")},
{"backup-dir", false, new StringField(&backup_dir, kDefaultBackupDir)},
{"log-dir", true, new StringField(&log_dir, "")},
{"log-level", false, new EnumField<int>(&log_level, log_levels, google::INFO)},
Expand Down
4 changes: 4 additions & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ struct Config {
std::string replica_announce_ip;
uint32_t replica_announce_port = 0;

// The following option exists so users can spawn a read-only server from a snapshot
// of a running server.
std::string snapshot_dir;

bool persist_cluster_nodes_enabled = true;
bool slot_id_encoded = false;
bool cluster_enabled = false;
Expand Down
44 changes: 44 additions & 0 deletions src/storage/storage.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "redis_metadata.h"
#include "rocksdb/cache.h"
#include "rocksdb_crc32c.h"
#include "scope_exit.h"
#include "server/server.h"
#include "storage/batch_indexer.h"
#include "table_properties_collector.h"
Expand Down Expand Up @@ -75,6 +76,37 @@ const int64_t kIORateLimitMaxMb = 1024000;

using rocksdb::Slice;

static Status CreateSnapshot(Config &config) {
// The Storage destructor deletes anything at the checkpoint_dir, so we need to make
// sure it's empty in case the user happens to use a snapshot name which matches the
// default (checkpoint/)
const std::string old_checkpoint_dir = std::exchange(config.checkpoint_dir, "");
const auto checkpoint_dir_guard =
MakeScopeExit([&config, &old_checkpoint_dir] { config.checkpoint_dir = old_checkpoint_dir; });

// Since .Open() will call `CreateSnapshot` if `snapshot_dir` is set, we need to
// clear it, and reset it after the snapshot is created to preserve symmetry.
const std::string snapshot_dir = std::exchange(config.snapshot_dir, "");
const auto snapshot_dir_guard = MakeScopeExit([&config, &snapshot_dir] { config.snapshot_dir = snapshot_dir; });

engine::Storage storage(&config);
if (const auto s = storage.Open(kDBOpenModeForReadOnly); !s.IsOK()) {
return {Status::NotOK, fmt::format("failed to open DB in read-only mode: {}", s.Msg())};
}

rocksdb::Checkpoint *snapshot = nullptr;
if (const auto s = rocksdb::Checkpoint::Create(storage.GetDB(), &snapshot); !s.ok()) {
return {Status::NotOK, s.ToString()};
}

std::unique_ptr<rocksdb::Checkpoint> snapshot_guard(snapshot);
if (const auto s = snapshot->CreateCheckpoint(snapshot_dir + "/db"); !s.ok()) {
return {Status::NotOK, s.ToString()};
}

return Status::OK();
}

Storage::Storage(Config *config)
: backup_creating_time_secs_(util::GetTimeStamp<std::chrono::seconds>()),
env_(rocksdb::Env::Default()),
Expand Down Expand Up @@ -267,6 +299,18 @@ Status Storage::CreateColumnFamilies(const rocksdb::Options &options) {
}

Status Storage::Open(DBOpenMode mode) {
// If a snapshot directory was specified, create a snapshot and open the database
// there in read-only mode.
if (config_->snapshot_dir != "") {
if (auto s = CreateSnapshot(*config_); !s.IsOK()) {
return s;
}
LOG(INFO) << "Starting server in read-only mode with snapshot dir: " << config_->snapshot_dir;
config_->dir = config_->snapshot_dir;
config_->db_dir = config_->snapshot_dir + "/db";
mode = DBOpenMode::kDBOpenModeForReadOnly;
}

auto guard = WriteLockGuard();
db_closing_ = false;

Expand Down
1 change: 0 additions & 1 deletion src/storage/storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <rocksdb/utilities/write_batch_with_index.h>

#include <atomic>
#include <cinttypes>
#include <cstddef>
#include <memory>
#include <shared_mutex>
Expand Down
Loading