Skip to content

Commit 912cae4

Browse files
authored
Limit proxy's memory from TiFlash's side (#408) (#425)
1 parent 37eb1f1 commit 912cae4

File tree

8 files changed

+370
-7
lines changed

8 files changed

+370
-7
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ unset-override:
211211

212212
pre-format: unset-override
213213
@rustup component add rustfmt
214-
@cargo install --force -q cargo-sort
214+
@cargo install --locked --force -q cargo-sort
215215

216216
ci_fmt_check:
217217
M="fmt" ./proxy_scripts/ci_check.sh

components/raftstore/src/store/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ impl Default for Config {
396396
apply_yield_duration: ReadableDuration::millis(500),
397397
apply_yield_write_size: ReadableSize::kb(32),
398398
perf_level: PerfLevel::Uninitialized,
399-
evict_cache_on_memory_ratio: 0.0,
399+
evict_cache_on_memory_ratio: 0.1,
400400
cmd_batch: true,
401401
cmd_batch_concurrent_ready_max_count: 1,
402402
raft_write_size_limit: ReadableSize::mb(1),

proxy_scripts/ci_check.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ elif [[ $M == "testold" ]]; then
2323
cargo test --features "$ENABLE_FEATURES" --package tests --test failpoints cases::test_transaction
2424
cargo test --features "$ENABLE_FEATURES" --package tests --test failpoints cases::test_cmd_epoch_checker
2525
# cargo test --package tests --test failpoints cases::test_disk_full
26-
cargo test --package tests --test failpoints cases::test_merge
26+
# cargo test --package tests --test failpoints cases::test_merge
2727
# cargo test --package tests --test failpoints cases::test_snap
28-
cargo test --package tests --test failpoints cases::test_import_service
28+
# cargo test --package tests --test failpoints cases::test_import_service
2929
elif [[ $M == "testnew" ]]; then
3030
export ENGINE_LABEL_VALUE=tiflash
3131
export RUST_BACKTRACE=full

proxy_server/src/config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,14 @@ impl Default for ProxyConfig {
273273
raftdb: RaftDbConfig::default(),
274274
storage: StorageConfig::default(),
275275
enable_io_snoop: false,
276+
// Previously, we set `memory_usage_high_water` to 0.1, in order to make TiFlash to be
277+
// always in a high-water situation. thus by setting
278+
// `evict_cache_on_memory_ratio`, we can evict entry cache if there is a memory usage
279+
// peak after restart. However there're some cases that the raftstore could
280+
// take more than 5% of the total used memory, so TiFlash will reject
281+
// msgAppend to every region. So, it actually not a good idea to make
282+
// TiFlash Proxy always run in a high-water state, in order to reduce the
283+
// memory usage peak after restart.
276284
readpool: ReadPoolConfig::default(),
277285
import: ImportConfig::default(),
278286
}

proxy_server/src/proxy.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,23 @@ pub unsafe fn run_proxy(
267267
.long("only-decryption")
268268
.help("Only do decryption in Proxy"),
269269
)
270+
.arg(
271+
Arg::with_name("memory-limit-size")
272+
.long("memory-limit-size")
273+
.help("Used as the maximum memory we can consume, in bytes")
274+
.takes_value(true),
275+
)
276+
.arg(
277+
Arg::with_name("memory-limit-ratio")
278+
.long("memory-limit-ratio")
279+
.help("Used as the maximum memory we can consume, in percentage")
280+
.takes_value(true),
281+
)
270282
.get_matches_from(args);
271283

272284
if matches.is_present("print-sample-config") {
273285
let config = TikvConfig::default();
274286
println!("{}", toml::to_string_pretty(&config).unwrap());
275-
process::exit(0);
276287
}
277288

278289
let mut unrecognized_keys = Vec::new();
@@ -308,6 +319,7 @@ pub unsafe fn run_proxy(
308319
if matches.is_present("only-decryption") {
309320
crate::run::run_tikv_only_decryption(config, proxy_config, engine_store_server_helper);
310321
} else {
322+
// Log is enabled here.
311323
crate::run::run_tikv_proxy(config, proxy_config, engine_store_server_helper);
312324
}
313325
}

proxy_server/src/setup.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::borrow::ToOwned;
55
use clap::ArgMatches;
66
use collections::HashMap;
77
pub use server::setup::initial_logger;
8-
use tikv::config::{MetricConfig, TikvConfig};
9-
use tikv_util::{self, logger};
8+
use tikv::config::{MetricConfig, TikvConfig, MEMORY_USAGE_LIMIT_RATE};
9+
use tikv_util::{self, config::ReadableSize, logger, sys::SysQuota};
1010

1111
use crate::config::ProxyConfig;
1212
pub use crate::fatal;
@@ -142,4 +142,49 @@ pub fn overwrite_config_with_cmd_args(
142142
.unwrap(),
143143
),
144144
);
145+
146+
let mut memory_limit_set = config.memory_usage_limit.is_some();
147+
if !memory_limit_set {
148+
if let Some(s) = matches.value_of("memory-limit-size") {
149+
let result: Result<u64, _> = s.parse();
150+
if let Ok(memory_limit_size) = result {
151+
info!(
152+
"overwrite memory_usage_limit by `memory-limit-size` to {}",
153+
memory_limit_size
154+
);
155+
config.memory_usage_limit = Some(ReadableSize(memory_limit_size));
156+
memory_limit_set = true;
157+
} else {
158+
info!("overwrite memory_usage_limit by `memory-limit-size` failed"; "memory_limit_size" => s);
159+
}
160+
}
161+
}
162+
163+
let total = SysQuota::memory_limit_in_bytes();
164+
if !memory_limit_set {
165+
if let Some(s) = matches.value_of("memory-limit-ratio") {
166+
let result: Result<f64, _> = s.parse();
167+
if let Ok(memory_limit_ratio) = result {
168+
if memory_limit_ratio <= 0.0 || memory_limit_ratio > 1.0 {
169+
info!("overwrite memory_usage_limit meets error ratio"; "ratio" => memory_limit_ratio);
170+
} else {
171+
let limit = (total as f64 * memory_limit_ratio) as u64;
172+
info!(
173+
"overwrite memory_usage_limit by `memory-limit-ratio`={} to {}",
174+
memory_limit_ratio, limit
175+
);
176+
config.memory_usage_limit = Some(ReadableSize(limit));
177+
memory_limit_set = true;
178+
}
179+
} else {
180+
info!("overwrite memory_usage_limit meets error ratio"; "ratio" => s);
181+
}
182+
}
183+
}
184+
185+
if !memory_limit_set && config.memory_usage_limit.is_none() {
186+
let limit = (total as f64 * MEMORY_USAGE_LIMIT_RATE) as u64;
187+
info!("overwrite memory_usage_limit failed, use TiKV's default"; "limit" => limit);
188+
config.memory_usage_limit = Some(ReadableSize(limit));
189+
}
145190
}

proxy_tests/proxy/config.rs

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use proxy_server::{
88
proxy::{gen_proxy_config, gen_tikv_config},
99
setup::overwrite_config_with_cmd_args,
1010
};
11+
use tikv::config::MEMORY_USAGE_LIMIT_RATE;
1112
use tikv_util::sys::SysQuota;
1213

1314
use crate::proxy::*;
@@ -122,6 +123,11 @@ fn test_config_proxy_default_no_config_item() {
122123
std::cmp::min(256, (cpu_num * 8.0) as usize)
123124
);
124125
assert_eq!(config.server.status_thread_pool_size, 2);
126+
127+
assert_eq!(config.raft_store.evict_cache_on_memory_ratio, 0.1);
128+
assert_eq!(config.memory_usage_high_water, 0.9);
129+
// Seems #244 doesn't goes into this branch.
130+
assert_eq!(config.server.reject_messages_on_memory_ratio, 0.2);
125131
}
126132

127133
/// We test if the engine-label is set properly.
@@ -200,3 +206,149 @@ apply-low-priority-pool-size = 41
200206
config.raft_store.apply_batch_system.low_priority_pool_size
201207
);
202208
}
209+
210+
#[test]
211+
fn test_memory_limit_overwrite() {
212+
let app = App::new("RaftStore Proxy")
213+
.arg(
214+
Arg::with_name("memory-limit-size")
215+
.long("memory-limit-size")
216+
.help("Used as the maximum memory we can consume, in bytes")
217+
.takes_value(true),
218+
)
219+
.arg(
220+
Arg::with_name("memory-limit-ratio")
221+
.long("memory-limit-ratio")
222+
.help("Used as the maximum memory we can consume, in percentage")
223+
.takes_value(true),
224+
);
225+
226+
let bootstrap = |args: Vec<&str>| {
227+
let mut v: Vec<String> = vec![];
228+
let matches = app.clone().get_matches_from(args);
229+
let mut config = gen_tikv_config(&None, false, &mut v);
230+
let mut proxy_config = gen_proxy_config(&None, false, &mut v);
231+
proxy_config.raftdb.defaultcf.block_cache_size = ReadableSize(0);
232+
proxy_config.rocksdb.defaultcf.block_cache_size = ReadableSize(0);
233+
proxy_config.rocksdb.lockcf.block_cache_size = ReadableSize(0);
234+
proxy_config.rocksdb.writecf.block_cache_size = ReadableSize(0);
235+
overwrite_config_with_cmd_args(&mut config, &mut proxy_config, &matches);
236+
address_proxy_config(&mut config, &proxy_config);
237+
config.compatible_adjust();
238+
config
239+
};
240+
241+
{
242+
let args = vec![
243+
"test_memory_limit_overwrite1",
244+
"--memory-limit-size",
245+
"12345",
246+
];
247+
let mut config = bootstrap(args);
248+
assert!(config.validate().is_ok());
249+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(12345)));
250+
}
251+
252+
{
253+
let args = vec![
254+
"test_memory_limit_overwrite2",
255+
"--memory-limit-size",
256+
"12345",
257+
"--memory-limit-ratio",
258+
"0.9",
259+
];
260+
let mut config = bootstrap(args);
261+
assert!(config.validate().is_ok());
262+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(12345)));
263+
}
264+
265+
let total = SysQuota::memory_limit_in_bytes();
266+
{
267+
let args = vec![
268+
"test_memory_limit_overwrite3",
269+
"--memory-limit-ratio",
270+
"0.800000",
271+
];
272+
let mut config = bootstrap(args);
273+
assert!(config.validate().is_ok());
274+
let limit = (total as f64 * 0.8) as u64;
275+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(limit)));
276+
}
277+
278+
let default_limit = (total as f64 * MEMORY_USAGE_LIMIT_RATE) as u64;
279+
{
280+
let args = vec![
281+
"test_memory_limit_overwrite4",
282+
"--memory-limit-ratio",
283+
"7.9",
284+
];
285+
let mut config = bootstrap(args);
286+
assert!(config.validate().is_ok());
287+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(default_limit)));
288+
}
289+
290+
{
291+
let args = vec![
292+
"test_memory_limit_overwrite5",
293+
"--memory-limit-ratio",
294+
"'-0.9'",
295+
];
296+
let mut config = bootstrap(args);
297+
assert!(config.validate().is_ok());
298+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(default_limit)));
299+
}
300+
301+
{
302+
let args = vec!["test_memory_limit_overwrite6"];
303+
let mut config = bootstrap(args);
304+
assert!(config.validate().is_ok());
305+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(default_limit)));
306+
}
307+
308+
let bootstrap2 = |args: Vec<&str>| {
309+
let mut v: Vec<String> = vec![];
310+
let matches = app.clone().get_matches_from(args);
311+
let mut file = tempfile::NamedTempFile::new().unwrap();
312+
write!(
313+
file,
314+
"
315+
memory-usage-limit = 42
316+
"
317+
)
318+
.unwrap();
319+
let path = file.path();
320+
let cpath = Some(path.as_os_str());
321+
let mut config = gen_tikv_config(&cpath, false, &mut v);
322+
let mut proxy_config = gen_proxy_config(&cpath, false, &mut v);
323+
proxy_config.raftdb.defaultcf.block_cache_size = ReadableSize(0);
324+
proxy_config.rocksdb.defaultcf.block_cache_size = ReadableSize(0);
325+
proxy_config.rocksdb.lockcf.block_cache_size = ReadableSize(0);
326+
proxy_config.rocksdb.writecf.block_cache_size = ReadableSize(0);
327+
overwrite_config_with_cmd_args(&mut config, &mut proxy_config, &matches);
328+
address_proxy_config(&mut config, &proxy_config);
329+
config.compatible_adjust();
330+
config
331+
};
332+
333+
{
334+
let args = vec![
335+
"test_memory_limit_nooverwrite3",
336+
"--memory-limit-ratio",
337+
"0.800000",
338+
];
339+
let mut config = bootstrap2(args);
340+
assert!(config.validate().is_ok());
341+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(42)));
342+
}
343+
344+
{
345+
let args = vec![
346+
"test_memory_limit_nooverwrite1",
347+
"--memory-limit-size",
348+
"12345",
349+
];
350+
let mut config = bootstrap2(args);
351+
assert!(config.validate().is_ok());
352+
assert_eq!(config.memory_usage_limit, Some(ReadableSize(42)));
353+
}
354+
}

0 commit comments

Comments
 (0)