baidu / braft

An industrial-grade C++ implementation of RAFT consensus algorithm based on brpc, widely used inside Baidu to build highly-available distributed systems.
Apache License 2.0
3.84k stars 862 forks source link

optimize get term #438

Open CkTD opened 4 months ago

CkTD commented 4 months ago

leader 上 _logs_in_memory 中缓存的 LogEntry 会在 apply 完成且写到盘上后被清理掉。 leader 在 append_entries rpc 中需要获取 prev_log_term。

如果请求的并发比较小,发送新Log时,前一个LogEntry 很有可能已经从缓存清理掉了,prev_log_term 只能从 LogStorage 获取。(场景: 一个server上,node 数量特别多,但是单个node qps 比较小,能观察到 bvar raft_read_term_from_storage_second 很高)

这个 pr 在 clear_memory_logs 时多保留 log,使得上面场景总能通过缓存查询到 prev_log_term。 如果长时间不写,最后这个保留的 log 会在打快照的时候被清理掉。

ehds commented 3 months ago

即使是从 LogStorage get_term, 在初始化时 每个 segment 都会缓存其 meta 信息(index->(term,offset)),所以也只是需要查找内存。 比起读 memoryLog ,会多一次查找 segment 和读取 meta 的开销(也会多一些判断和内存跳转以及锁的开销)。如果是 qps 比较低的情况,有评估过对性能的影响有多大吗?

CkTD commented 1 month ago

即使是从 LogStorage get_term, 在初始化时 每个 segment 都会缓存其 meta 信息(index->(term,offset)),所以也只是需要查找内存。 比起读 memoryLog ,会多一次查找 segment 和读取 meta 的开销(也会多一些判断和内存跳转以及锁的开销)。如果是 qps 比较低的情况,有评估过对性能的影响有多大吗?

我这里的测试场景下 AppendEntries RPC 的时延 < 1ms。 一个 node get_term 的频率能达到每秒上千次。

测试性能的时候是用了一个自己开发的LogStorage,用 contention profiler 能看到由于读term造成的锁竞争比较明显。默认的 LogStorage还没观察过