Skip to content

Commit 6cb413c

Browse files
Mixficsolwuxianrong
andauthored
rsync rate limiting configuration (#1926)
Co-authored-by: wuxianrong <wuxianrong@360.cn>
1 parent 4a39505 commit 6cb413c

8 files changed

Lines changed: 105 additions & 22 deletions

File tree

conf/pika.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,3 +410,7 @@ default-slot-num : 1024
410410
# blob-num-shard-bits default -1, the number of bits from cache keys to be use as shard id.
411411
# The cache will be sharded into 2^blob-num-shard-bits shards.
412412
# blob-num-shard-bits : -1
413+
414+
# Rsync Rate limiting configuration
415+
throttle-bytes-per-second : 307200000
416+
max-rsync-parallel-num : 4

include/pika_admin.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -450,16 +450,16 @@ class HelloCmd : public Cmd {
450450
};
451451

452452
class DiskRecoveryCmd : public Cmd {
453-
public:
454-
DiskRecoveryCmd(const std::string& name, int arity, uint16_t flag) : Cmd(name, arity, flag) {}
455-
void Do(std::shared_ptr<Slot> slot = nullptr) override;
456-
void Split(std::shared_ptr<Slot> slot, const HintKeys& hint_keys) override{};
457-
void Merge() override{};
458-
Cmd* Clone() override { return new DiskRecoveryCmd(*this); }
459-
460-
private:
461-
void DoInitial() override;
462-
std::map<std::string, uint64_t> background_errors_;
453+
public:
454+
DiskRecoveryCmd(const std::string& name, int arity, uint16_t flag) : Cmd(name, arity, flag) {}
455+
void Do(std::shared_ptr<Slot> slot = nullptr) override;
456+
void Split(std::shared_ptr<Slot> slot, const HintKeys& hint_keys) override{};
457+
void Merge() override{};
458+
Cmd* Clone() override { return new DiskRecoveryCmd(*this); }
459+
460+
private:
461+
void DoInitial() override;
462+
std::map<std::string, uint64_t> background_errors_;
463463
};
464464

465465
#ifdef WITH_COMMAND_DOCS

include/pika_conf.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,15 @@ class PikaConf : public pstd::BaseConf {
328328
int64_t blob_cache() { return blob_cache_; }
329329
int64_t blob_num_shard_bits() { return blob_num_shard_bits_; }
330330

331+
// Rsync Rate limiting configuration
332+
int throttle_bytes_per_second() {
333+
std::shared_lock l(rwlock_);
334+
return throttle_bytes_per_second_;
335+
}
336+
int max_rsync_parallel_num() {
337+
std::shared_lock l(rwlock_);
338+
return max_rsync_parallel_num_;
339+
}
331340
// Immutable config items, we don't use lock.
332341
bool daemonize() { return daemonize_; }
333342
std::string pidfile() { return pidfile_; }
@@ -544,6 +553,19 @@ class PikaConf : public pstd::BaseConf {
544553
log_level_ = value;
545554
}
546555

556+
// Rsync Rate limiting configuration
557+
void SetThrottleBytesPerSecond(const int value) {
558+
std::lock_guard l(rwlock_);
559+
TryPushDiffCommands("throttle-bytes-per-second", std::to_string(value));
560+
throttle_bytes_per_second_ = value;
561+
}
562+
563+
void SetMaxRsyncParallelNum(const int value) {
564+
std::lock_guard l(rwlock_);
565+
TryPushDiffCommands("max-rsync-parallel-num", std::to_string(value));
566+
max_rsync_parallel_num_ = value;
567+
}
568+
547569
pstd::Status DBSlotsSanityCheck(const std::string& db_name, const std::set<uint32_t>& slot_ids,
548570
bool is_add);
549571
pstd::Status AddDBSlots(const std::string& db_name, const std::set<uint32_t>& slot_ids);
@@ -666,6 +688,10 @@ class PikaConf : public pstd::BaseConf {
666688
std::unique_ptr<PikaMeta> local_meta_;
667689

668690
std::shared_mutex rwlock_;
691+
692+
// Rsync Rate limiting configuration
693+
int throttle_bytes_per_second_ = 307200000;
694+
int max_rsync_parallel_num_ = 4;
669695
};
670696

671697
#endif

include/rsync_client.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "include/throttle.h"
3030
#include "rsync_service.pb.h"
3131

32+
extern std::unique_ptr<PikaConf> g_pika_conf;
33+
3234
const std::string kDumpMetaFileName = "DUMP_META_DATA";
3335
const std::string kUuidPrefix = "snapshot-uuid:";
3436

@@ -50,6 +52,7 @@ class RsyncClient : public net::Thread {
5052
void* ThreadMain() override;
5153
void Copy(const std::set<std::string>& file_set, int index);
5254
bool Init();
55+
int GetParallelNum();
5356
Status Start();
5457
Status Stop();
5558
bool IsRunning() {
@@ -93,9 +96,9 @@ class RsyncClient : public net::Thread {
9396
std::condition_variable cond_;
9497
std::mutex mu_;
9598

96-
std::unique_ptr<Throttle> throttle_;
9799
std::string master_ip_;
98100
int master_port_;
101+
int parallel_num_;
99102
};
100103

101104
class RsyncWriter {

include/throttle.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#include <atomic>
1010
#include "pstd/include/pstd_mutex.h"
11+
#include "pika_conf.h"
12+
13+
extern std::unique_ptr<PikaConf> g_pika_conf;
1114

1215
namespace rsync {
1316
class Throttle {
@@ -17,6 +20,10 @@ class Throttle {
1720
~Throttle();
1821
size_t ThrottledByThroughput(size_t bytes);
1922
void ReturnUnusedThroughput(size_t acquired, size_t consumed, size_t elaspe_time_us);
23+
static Throttle& GetInstance() {
24+
static Throttle instance(g_pika_conf->throttle_bytes_per_second(), 10);
25+
return instance;
26+
}
2027

2128
private:
2229
std::atomic<size_t> throttle_throughput_bytes_ = 100 * 1024 * 1024;

src/pika_admin.cc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,17 @@ void ConfigCmd::ConfigGet(std::string& ret) {
18361836
EncodeString(&config_body, "slave-read-only");
18371837
EncodeString(&config_body, g_pika_conf->slave_read_only() ? "yes" : "no");
18381838
}
1839+
if (pstd::stringmatch(pattern.data(), "throttle-bytes-per-second", 1) != 0) {
1840+
elements += 2;
1841+
EncodeString(&config_body, "throttle-bytes-per-second");
1842+
EncodeNumber(&config_body, g_pika_conf->throttle_bytes_per_second());
1843+
}
1844+
1845+
if (pstd::stringmatch(pattern.data(), "max-rsync-parallel-num", 1) != 0) {
1846+
elements += 2;
1847+
EncodeString(&config_body, "max-rsync-parallel-num");
1848+
EncodeNumber(&config_body, g_pika_conf->max_rsync_parallel_num());
1849+
}
18391850

18401851
std::stringstream resp;
18411852
resp << "*" << std::to_string(elements) << "\r\n" << config_body;
@@ -1879,6 +1890,8 @@ void ConfigCmd::ConfigSet(std::string& ret) {
18791890
EncodeString(&ret, "write-buffer-size");
18801891
EncodeString(&ret, "max-write-buffer-num");
18811892
EncodeString(&ret, "arena-block-size");
1893+
EncodeString(&ret, "throttle-bytes-per-second");
1894+
EncodeString(&ret, "max-rsync-parallel-num");
18821895
return;
18831896
}
18841897
long int ival;
@@ -2161,6 +2174,20 @@ void ConfigCmd::ConfigSet(std::string& ret) {
21612174
}
21622175
g_pika_conf->SetArenaBlockSize(static_cast<int>(ival));
21632176
ret = "+OK\r\n";
2177+
} else if (set_item == "throttle-bytes-per-second") {
2178+
if ((pstd::string2int(value.data(), value.size(), &ival) == 0) || ival <= 0) {
2179+
ret = "-ERR Invalid argument \'" + value + "\' for CONFIG SET 'throttle-bytes-per-second'\r\n";
2180+
return;
2181+
}
2182+
g_pika_conf->SetThrottleBytesPerSecond(static_cast<int>(ival));
2183+
ret = "+OK\r\n";
2184+
} else if (set_item == "max-rsync-parallel-num") {
2185+
if ((pstd::string2int(value.data(), value.size(), &ival) == 0) || ival > kMaxRsyncParallelNum) {
2186+
ret = "-ERR Invalid argument \'" + value + "\' for CONFIG SET 'max-rsync-parallel-num'\r\n";
2187+
return;
2188+
}
2189+
g_pika_conf->SetMaxRsyncParallelNum(static_cast<int>(ival));
2190+
ret = "+OK\r\n";
21642191
} else {
21652192
ret = "-ERR Unsupported CONFIG parameter: " + set_item + "\r\n";
21662193
}

src/pika_conf.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,17 @@ int PikaConf::Load() {
601601
GetConfInt64("blob-num-shard-bits", &blob_num_shard_bits_);
602602

603603
return ret;
604+
605+
// throttle-bytes-per-second
606+
GetConfInt("throttle-bytes-per-second", &throttle_bytes_per_second_);
607+
if (throttle_bytes_per_second_ <= 0) {
608+
throttle_bytes_per_second_ = 307200000;
609+
}
610+
611+
GetConfInt("max-rsync-parallel-num", &max_rsync_parallel_num_);
612+
if (max_rsync_parallel_num_ <= 0) {
613+
max_rsync_parallel_num_ = 4;
614+
}
604615
}
605616

606617
void PikaConf::TryPushDiffCommands(const std::string& command, const std::string& value) {
@@ -641,6 +652,8 @@ int PikaConf::ConfigRewrite() {
641652
SetConfInt64("manually-resume-interval", resume_check_interval_);
642653
SetConfDouble("min-check-resume-ratio", min_check_resume_ratio_);
643654
SetConfInt("slave-priority", slave_priority_);
655+
SetConfInt("throttle-bytes-per-second", throttle_bytes_per_second_);
656+
SetConfInt("max-rsync-parallel-num", max_rsync_parallel_num_);
644657
SetConfInt("sync-window-size", sync_window_size_.load());
645658
SetConfInt("consensus-level", consensus_level_.load());
646659
SetConfInt("replication-num", replication_num_.load());

src/rsync_client.cc

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,17 @@ using namespace RsyncService;
1818
extern PikaServer* g_pika_server;
1919

2020
const int kFlushIntervalUs = 10 * 1000 * 1000;
21-
const int kThrottleBytesPerSecond = 300 << 20;
2221
const int kBytesPerRequest = 4 << 20;
2322
const int kThrottleCheckCycle = 10;
2423

2524
namespace rsync {
2625
RsyncClient::RsyncClient(const std::string& dir, const std::string& db_name, const uint32_t slot_id)
2726
: snapshot_uuid_(""), dir_(dir), db_name_(db_name), slot_id_(slot_id),
28-
state_(IDLE), max_retries_(10), master_ip_(""), master_port_(0) {
27+
state_(IDLE), max_retries_(10), master_ip_(""), master_port_(0),
28+
parallel_num_(g_pika_conf->max_rsync_parallel_num()) {
2929
wo_mgr_.reset(new WaitObjectManager());
3030
client_thread_ = std::make_unique<RsyncClientThread>(3000, 60, wo_mgr_.get());
31-
work_threads_.resize(kMaxRsyncParallelNum);
32-
throttle_.reset(new Throttle(kThrottleBytesPerSecond, kThrottleCheckCycle));
31+
work_threads_.resize(GetParallelNum());
3332
finished_work_cnt_.store(0);
3433
}
3534

@@ -83,13 +82,13 @@ void* RsyncClient::ThreadMain() {
8382

8483
Status s = Status::OK();
8584
LOG(INFO) << "RsyncClient begin to copy remote files";
86-
std::vector<std::set<std::string> > file_vec(kMaxRsyncParallelNum);
85+
std::vector<std::set<std::string> > file_vec(GetParallelNum());
8786
int index = 0;
8887
for (const auto& file : file_set_) {
89-
file_vec[index++ % kMaxRsyncParallelNum].insert(file);
88+
file_vec[index++ % GetParallelNum()].insert(file);
9089
}
9190

92-
for (int i = 0; i < kMaxRsyncParallelNum; i++) {
91+
for (int i = 0; i < GetParallelNum(); i++) {
9392
work_threads_[i] = std::move(std::thread(&RsyncClient::Copy, this, file_vec[i], i));
9493
}
9594

@@ -126,12 +125,12 @@ void* RsyncClient::ThreadMain() {
126125
outfile.flush();
127126
meta_rep.clear();
128127

129-
if (finished_work_cnt_.load() == kMaxRsyncParallelNum) {
128+
if (finished_work_cnt_.load() == GetParallelNum()) {
130129
break;
131130
}
132131
}
133132

134-
for (int i = 0; i < kMaxRsyncParallelNum; i++) {
133+
for (int i = 0; i < GetParallelNum(); i++) {
135134
work_threads_[i].join();
136135
}
137136
finished_work_cnt_.store(0);
@@ -161,7 +160,7 @@ Status RsyncClient::CopyRemoteFile(const std::string& filename, int index) {
161160
break;
162161
}
163162
size_t copy_file_begin_time = pstd::NowMicros();
164-
size_t count = throttle_->ThrottledByThroughput(kBytesPerRequest);
163+
size_t count = Throttle::GetInstance().ThrottledByThroughput(kBytesPerRequest);
165164
if (count == 0) {
166165
std::this_thread::sleep_for(std::chrono::milliseconds(1000 / kThrottleCheckCycle));
167166
continue;
@@ -200,7 +199,7 @@ Status RsyncClient::CopyRemoteFile(const std::string& filename, int index) {
200199

201200
size_t ret_count = resp->file_resp().count();
202201
size_t elaspe_time_us = pstd::NowMicros() - copy_file_begin_time;
203-
throttle_->ReturnUnusedThroughput(count, ret_count, elaspe_time_us);
202+
Throttle::GetInstance().ReturnUnusedThroughput(count, ret_count, elaspe_time_us);
204203

205204
if (resp->code() != RsyncService::kOk) {
206205
//TODO: handle different error
@@ -492,5 +491,9 @@ std::string RsyncClient::GetLocalMetaFilePath() {
492491
return db_path + kDumpMetaFileName;
493492
}
494493

494+
int RsyncClient::GetParallelNum() {
495+
return parallel_num_;
496+
}
497+
495498
} // end namespace rsync
496499

0 commit comments

Comments
 (0)