This is an automated email from the ASF dual-hosted git repository.
hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 859953b84 feat(config): allow to configure the
rocksdb.sst_file_delete_rate_bytes_per_sec (#3040)
859953b84 is described below
commit 859953b84fcb6ef3967414b33c9fa233b660038f
Author: sryan yuan <[email protected]>
AuthorDate: Fri Jun 27 16:41:29 2025 +0800
feat(config): allow to configure the
rocksdb.sst_file_delete_rate_bytes_per_sec (#3040)
---
kvrocks.conf | 11 +++++++++++
src/config/config.cc | 8 ++++++++
src/config/config.h | 1 +
src/storage/storage.cc | 7 ++++++-
src/storage/storage.h | 2 ++
tests/cppunit/config_test.cc | 1 +
tests/gocase/unit/config/config_test.go | 24 ++++++++++++++++++++++++
7 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/kvrocks.conf b/kvrocks.conf
index 25172cb88..96e9b05bc 100644
--- a/kvrocks.conf
+++ b/kvrocks.conf
@@ -1066,5 +1066,16 @@ rocksdb.partition_filters yes
# Default: 0
rocksdb.max_compaction_bytes 0
+# Set the delete rate limit in bytes per second for SST files deletion.
+# zero means disable delete rate limiting and delete files immediately.
+# In scenarios involving frequent database iterations (e.g., HGETALL, SCAN)
obsolete WAL files
+# may be deleted synchronously, causing latency spikes. Enabling this option
activates a
+# controlled slow deletion mechanism, which also resolves WAL deletion latency
issues when
+# an iterator is released.
+# see https://github.com/facebook/rocksdb/wiki/Slow-Deletion
+#
+# Default: 0
+rocksdb.sst_file_delete_rate_bytes_per_sec 0
+
################################ NAMESPACE
#####################################
# namespace.test change.me
diff --git a/src/config/config.cc b/src/config/config.cc
index 24a9a2582..1e561fe6d 100644
--- a/src/config/config.cc
+++ b/src/config/config.cc
@@ -302,6 +302,8 @@ Config::Config() {
{"rocksdb.avoid_unnecessary_blocking_io", true, new
YesNoField(&rocks_db.avoid_unnecessary_blocking_io, true)},
{"rocksdb.partition_filters", true, new
YesNoField(&rocks_db.partition_filters, true)},
{"rocksdb.max_compaction_bytes", false, new
Int64Field(&rocks_db.max_compaction_bytes, 0, 0, INT64_MAX)},
+ {"rocksdb.sst_file_delete_rate_bytes_per_sec", false,
+ new Int64Field(&rocks_db.sst_file_delete_rate_bytes_per_sec, 0, 0,
INT64_MAX)},
/* rocksdb write options */
{"rocksdb.write_options.sync", true, new
YesNoField(&rocks_db.write_options.sync, false)},
@@ -720,6 +722,12 @@ void Config::initFieldCallback() {
}
return
srv->storage->SetOptionForAllColumnFamilies(TrimRocksDbPrefix(k), v);
}},
+ {"rocksdb.sst_file_delete_rate_bytes_per_sec",
+ [this](Server *srv, [[maybe_unused]] const std::string &k,
[[maybe_unused]] const std::string &v) -> Status {
+ if (!srv) return Status::OK();
+
srv->storage->SetSstFileDeleteRateBytesPerSecond(rocks_db.sst_file_delete_rate_bytes_per_sec);
+ return Status::OK();
+ }},
{"rocksdb.max_open_files", set_db_option_cb},
{"rocksdb.stats_dump_period_sec", set_db_option_cb},
{"rocksdb.delayed_write_rate", set_db_option_cb},
diff --git a/src/config/config.h b/src/config/config.h
index 0b95b81ac..2dd415732 100644
--- a/src/config/config.h
+++ b/src/config/config.h
@@ -238,6 +238,7 @@ struct Config {
bool avoid_unnecessary_blocking_io = true;
bool partition_filters;
int64_t max_compaction_bytes;
+ int64_t sst_file_delete_rate_bytes_per_sec = 0;
struct WriteOptions {
bool sync;
diff --git a/src/storage/storage.cc b/src/storage/storage.cc
index 47afc5bf2..96eb931f3 100644
--- a/src/storage/storage.cc
+++ b/src/storage/storage.cc
@@ -194,7 +194,8 @@ rocksdb::Options Storage::InitRocksDBOptions() {
options.max_total_wal_size =
static_cast<uint64_t>(config_->rocks_db.max_total_wal_size * MiB);
options.listeners.emplace_back(new EventListener(this));
options.dump_malloc_stats = config_->rocks_db.dump_malloc_stats;
- sst_file_manager_ =
std::shared_ptr<rocksdb::SstFileManager>(rocksdb::NewSstFileManager(rocksdb::Env::Default()));
+ sst_file_manager_ =
std::shared_ptr<rocksdb::SstFileManager>(rocksdb::NewSstFileManager(
+ rocksdb::Env::Default(), nullptr, "",
config_->rocks_db.sst_file_delete_rate_bytes_per_sec));
options.sst_file_manager = sst_file_manager_;
int64_t max_io_mb = kIORateLimitMaxMb;
if (config_->max_io_mb > 0) max_io_mb = config_->max_io_mb;
@@ -922,6 +923,10 @@ uint64_t Storage::GetTotalSize(const std::string &ns) {
return total_size;
}
+void Storage::SetSstFileDeleteRateBytesPerSecond(int64_t delete_rate) {
+ sst_file_manager_->SetDeleteRateBytesPerSecond(delete_rate);
+}
+
void Storage::CheckDBSizeLimit() {
bool limit_reached = false;
if (config_->max_db_size > 0) {
diff --git a/src/storage/storage.h b/src/storage/storage.h
index 76b501a63..8ef807eca 100644
--- a/src/storage/storage.h
+++ b/src/storage/storage.h
@@ -31,6 +31,7 @@
#include <atomic>
#include <cinttypes>
#include <cstddef>
+#include <cstdint>
#include <memory>
#include <shared_mutex>
#include <string>
@@ -284,6 +285,7 @@ class Storage {
LockManager *GetLockManager() { return &lock_mgr_; }
void PurgeOldBackups(uint32_t num_backups_to_keep, uint32_t
backup_max_keep_hours);
uint64_t GetTotalSize(const std::string &ns = kDefaultNamespace);
+ void SetSstFileDeleteRateBytesPerSecond(int64_t delete_rate);
void CheckDBSizeLimit();
bool ReachedDBSizeLimit() { return db_size_limit_reached_; }
void SetDBSizeLimit(bool limit) { db_size_limit_reached_ = limit; }
diff --git a/tests/cppunit/config_test.cc b/tests/cppunit/config_test.cc
index 301c373ab..84c4cc385 100644
--- a/tests/cppunit/config_test.cc
+++ b/tests/cppunit/config_test.cc
@@ -84,6 +84,7 @@ TEST(Config, GetAndSet) {
{"rocksdb.level_compaction_dynamic_level_bytes", "yes"},
{"rocksdb.max_background_jobs", "4"},
{"rocksdb.compression_start_level", "2"},
+ {"rocksdb.sst_file_delete_rate_bytes_per_sec", "0"},
};
std::vector<std::string> values;
for (const auto &iter : mutable_cases) {
diff --git a/tests/gocase/unit/config/config_test.go
b/tests/gocase/unit/config/config_test.go
index 4d4636187..3287318ea 100644
--- a/tests/gocase/unit/config/config_test.go
+++ b/tests/gocase/unit/config/config_test.go
@@ -371,3 +371,27 @@ func TestConfigRocksDBOptions(t *testing.T) {
require.EqualValues(t, "1073741824", result[parameter])
})
}
+
+func TestConfigSstFileDeleteRateBytesPerSec(t *testing.T) {
+ t.Parallel()
+ srv := util.StartServer(t, map[string]string{})
+ defer srv.Close()
+
+ cli := srv.NewClient()
+ defer func() { require.NoError(t, cli.Close()) }()
+
+ t.Run("Get and Set rocksdb.sst_file_delete_rate_bytes_per_sec", func(t
*testing.T) {
+ ctx := context.Background()
+ parameter := "rocksdb.sst_file_delete_rate_bytes_per_sec"
+ result, err := cli.ConfigGet(ctx, parameter).Result()
+ require.NoError(t, err)
+ require.EqualValues(t, "0", result[parameter])
+
+ util.ErrorRegexp(t, cli.ConfigSet(ctx, parameter, "-1").Err(),
".*out of numeric range")
+
+ require.NoError(t, cli.ConfigSet(ctx, parameter,
"1073741824").Err())
+ result, err = cli.ConfigGet(ctx, parameter).Result()
+ require.NoError(t, err)
+ require.EqualValues(t, "1073741824", result[parameter])
+ })
+}