1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use configuration::{ConfigChange, ConfigManager, Configuration};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tikv_util::config::VersionTrack;
use tikv_util::info;
const DEFAULT_DETECT_TIMES: u64 = 10;
const DEFAULT_SAMPLE_THRESHOLD: u64 = 100;
pub(crate) const DEFAULT_SAMPLE_NUM: usize = 20;
const DEFAULT_QPS_THRESHOLD: usize = 3000;
const DEFAULT_BYTE_THRESHOLD: usize = 30 * 1024 * 1024;
const DEFAULT_SPLIT_BALANCE_SCORE: f64 = 0.25;
const DEFAULT_SPLIT_CONTAINED_SCORE: f64 = 0.5;
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Configuration)]
#[serde(default)]
#[serde(rename_all = "kebab-case")]
pub struct SplitConfig {
pub qps_threshold: usize,
pub split_balance_score: f64,
pub split_contained_score: f64,
pub detect_times: u64,
pub sample_num: usize,
pub sample_threshold: u64,
pub byte_threshold: usize,
#[config(skip)]
#[doc(hidden)]
#[serde(skip_serializing)]
pub size_threshold: Option<usize>,
#[config(skip)]
#[doc(hidden)]
#[serde(skip_serializing)]
pub key_threshold: Option<usize>,
}
impl Default for SplitConfig {
fn default() -> SplitConfig {
SplitConfig {
qps_threshold: DEFAULT_QPS_THRESHOLD,
split_balance_score: DEFAULT_SPLIT_BALANCE_SCORE,
split_contained_score: DEFAULT_SPLIT_CONTAINED_SCORE,
detect_times: DEFAULT_DETECT_TIMES,
sample_num: DEFAULT_SAMPLE_NUM,
sample_threshold: DEFAULT_SAMPLE_THRESHOLD,
byte_threshold: DEFAULT_BYTE_THRESHOLD,
size_threshold: None,
key_threshold: None,
}
}
}
impl SplitConfig {
pub fn validate(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
if self.split_balance_score > 1.0
|| self.split_balance_score < 0.0
|| self.split_contained_score > 1.0
|| self.split_contained_score < 0.0
{
return Err(
("split_balance_score or split_contained_score should be between 0 and 1.").into(),
);
}
if self.sample_num >= self.qps_threshold {
return Err(
("sample_num should be less than qps_threshold for load-base-split.").into(),
);
}
Ok(())
}
}
#[derive(Clone, Default)]
pub struct SplitConfigManager(pub Arc<VersionTrack<SplitConfig>>);
impl ConfigManager for SplitConfigManager {
fn dispatch(
&mut self,
change: ConfigChange,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
{
let change = change.clone();
self.0
.update(move |cfg: &mut SplitConfig| cfg.update(change));
}
info!(
"load base split config changed";
"change" => ?change,
);
Ok(())
}
}
impl std::ops::Deref for SplitConfigManager {
type Target = Arc<VersionTrack<SplitConfig>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}