Skip to content

Commit a9fb5dd

Browse files
authored
fix(meta-service): evict cache for purge raft-log (#17951)
When raft-log entries are purged, it should also be removed from the cache, since they will never be read again. This will just minimize the cache usage even it is configured with large max-items or capacity. We have added a test to ensure the behavoir of the raft-log cache.
1 parent 3a34bbf commit a9fb5dd

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ proptest = { version = "1", default-features = false, features = ["std"] }
443443
prost = { version = "0.13" }
444444
prost-build = { version = "0.13" }
445445
prqlc = "0.11.3"
446-
raft-log = { version = "0.2.7" }
446+
raft-log = { version = "0.2.9" }
447447
rand = { version = "0.8.5", features = ["small_rng"] }
448448
rand_distr = "0.4.3"
449449
rayon = "1.9.0"

src/meta/service/tests/it/store.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ use log::debug;
4141
use log::info;
4242
use maplit::btreeset;
4343
use pretty_assertions::assert_eq;
44+
use raft_log::DumpApi;
4445
use test_harness::test;
4546

4647
use crate::testing::meta_service_test_harness;
@@ -67,6 +68,70 @@ async fn test_impl_raft_storage() -> anyhow::Result<()> {
6768
Ok(())
6869
}
6970

71+
/// Ensure purged logs to be removed from the cache
72+
#[test(harness = meta_service_test_harness)]
73+
#[fastrace::trace]
74+
async fn test_meta_store_purge_cache() -> anyhow::Result<()> {
75+
let id = 3;
76+
let mut tc = MetaSrvTestContext::new(id);
77+
tc.config.raft_config.log_cache_max_items = 100;
78+
// Build with small chunk, because all entries in the last open chunk will be cached.
79+
tc.config.raft_config.log_wal_chunk_max_records = 5;
80+
81+
{
82+
let mut sto = RaftStore::open(&tc.config.raft_config).await?;
83+
84+
sto.save_vote(&Vote::new(10, 5)).await?;
85+
86+
sto.blocking_append([
87+
Entry::new_blank(log_id(1, 2, 1)),
88+
Entry::new_blank(log_id(1, 2, 2)),
89+
Entry::new_blank(log_id(1, 2, 3)),
90+
Entry::new_blank(log_id(1, 2, 4)),
91+
Entry::new_blank(log_id(1, 2, 5)),
92+
])
93+
.await?;
94+
95+
let stat = sto.log.read().await.stat();
96+
assert_eq!(stat.payload_cache_item_count, 5);
97+
98+
{
99+
let r = sto.log.read().await;
100+
let got = r.dump().write_to_string()?;
101+
println!("dump: {}", got);
102+
let want_dumped = r#"RaftLog:
103+
ChunkId(00_000_000_000_000_000_000)
104+
R-00000: [000_000_000, 000_000_018) Size(18): State(RaftLogState { vote: None, last: None, committed: None, purged: None, user_data: None })
105+
R-00001: [000_000_018, 000_000_046) Size(28): State(RaftLogState { vote: None, last: None, committed: None, purged: None, user_data: Some(LogStoreMeta { node_id: Some(3) }) })
106+
R-00002: [000_000_046, 000_000_096) Size(50): SaveVote(Cw(Vote { leader_id: LeaderId { term: 10, node_id: 5 }, committed: false }))
107+
R-00003: [000_000_096, 000_000_148) Size(52): Append(Cw(LogId { leader_id: LeaderId { term: 1, node_id: 2 }, index: 1 }), Cw(blank))
108+
R-00004: [000_000_148, 000_000_200) Size(52): Append(Cw(LogId { leader_id: LeaderId { term: 1, node_id: 2 }, index: 2 }), Cw(blank))
109+
ChunkId(00_000_000_000_000_000_200)
110+
R-00000: [000_000_000, 000_000_100) Size(100): State(RaftLogState { vote: Some(Cw(Vote { leader_id: LeaderId { term: 10, node_id: 5 }, committed: false })), last: Some(Cw(LogId { leader_id: LeaderId { term: 1, node_id: 2 }, index: 2 })), committed: None, purged: None, user_data: Some(LogStoreMeta { node_id: Some(3) }) })
111+
R-00001: [000_000_100, 000_000_152) Size(52): Append(Cw(LogId { leader_id: LeaderId { term: 1, node_id: 2 }, index: 3 }), Cw(blank))
112+
R-00002: [000_000_152, 000_000_204) Size(52): Append(Cw(LogId { leader_id: LeaderId { term: 1, node_id: 2 }, index: 4 }), Cw(blank))
113+
R-00003: [000_000_204, 000_000_256) Size(52): Append(Cw(LogId { leader_id: LeaderId { term: 1, node_id: 2 }, index: 5 }), Cw(blank))
114+
"#;
115+
assert_eq!(want_dumped, got);
116+
}
117+
118+
// When purging up to index=4, all entries in the last open chunk will still be cached.
119+
// All previous entries are purge, although the cache is not full.
120+
121+
sto.purge(log_id(1, 2, 4)).await?;
122+
123+
let r = sto.log.read().await;
124+
let got = r.dump().write_to_string()?;
125+
println!("dump: {}", got);
126+
127+
let stat = sto.log.read().await.stat();
128+
println!("stat: {:#}", stat);
129+
assert_eq!(stat.payload_cache_item_count, 3);
130+
}
131+
132+
Ok(())
133+
}
134+
70135
#[test(harness = meta_service_test_harness)]
71136
#[fastrace::trace]
72137
async fn test_meta_store_restart() -> anyhow::Result<()> {

0 commit comments

Comments
 (0)