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.95k stars 881 forks source link

Support log length based snapshot #318

Open ehds opened 3 years ago

ehds commented 3 years ago

Support log length based snapshot

PFZheng commented 3 years ago

在Closure里处理不是很优雅。这里是否可以抽象一个通用的机制,卡住未来的某个log index做snapshot(将log index提交给fsm caller的on_apply线程),这个未来可以扩展到一些额外的用途,例如做副本间的一致性校验(相同的log index的snapshot数据应该是等价的)。

然后具体到本issue,只需要在snapshot开始/完成时计算下一次的卡位点即可。

NodeImpl的参数上,可以增加一个snapshot方式的参数,interval/log length选一个。log length需要改一个更贴切的名字

ehds commented 3 years ago

在Closure里处理不是很优雅。这里是否可以抽象一个通用的机制,卡住未来的某个log index做snapshot(将log index提交给fsm caller的on_apply线程),这个未来可以扩展到一些额外的用途,例如做副本间的一致性校验(相同的log index的snapshot数据应该是等价的)。

然后具体到本issue,只需要在snapshot开始/完成时计算下一次的卡位点即可。

NodeImpl的参数上,可以增加一个snapshot方式的参数,interval/log length选一个。log length需要改一个更贴切的名字

卡住未来的某个 log index 做 snapshot,这 个 log index 一定要求是一个精确值吗?比如卡位点在 10, 那么 index 为 10 的 log apply之后就要做snapshot?

“(将log index提交给fsm caller的 on_apply 线程)" 这句话不是很理解,fsm caller 会在 do_commit 的时候会调用用户自己实现的on_apply,所以是等待用户on_apply 卡点 log 之后,开始do_snapshot吗?

PFZheng commented 3 years ago

现有的 snapshot 流程是由 int FSMCaller::on_snapshot_save(SaveSnapshotClosure* done) 触发的: https://github.com/baidu/braft/blob/f5fbf9299ea92e10948e735117f63dc3bbd21f1c/src/braft/fsm_caller.cpp#L321 在这个函数里会提交一个task到execution queue,和调用用户回调on_apply函数是一个线程。在同一个execution queue里做检查几乎没有冗余的开销,不需要像现在提交的这个patch检查较重。例如,一种改法是将在void FSMCaller::do_committed(int64_t committed_index)中将遍历日志的迭代器做一下修改,分成snapshot前和snapshot后两个,就可以在中间插入一个snapshot任务: https://github.com/baidu/braft/blob/f5fbf9299ea92e10948e735117f63dc3bbd21f1c/src/braft/fsm_caller.cpp#L279 这里的实现也有两种方式:

考虑到第二种做法未来可以有其它可扩展的用途,所以个人认为第二种做法更好。

ehds commented 3 years ago
  1. 增加SnapshotTriggerType参数(NONETIMERLOG_INTERVAL) 其中NONE不自动触发快照,TIME代表定时触发快照,LOG_INTERVSAL类型, 是当日志长度满足一定要求时触发,也就是说相邻两个快照之间的日志间隔数目是一定的。具体实现是在fsm_call 的 do_committed 中判断,当applied_index到达特定的 log index 点后原地触发snapshot。
  2. 之前的snapshot的接口都是向execution_queue提交任务,为了能够实现原地触发调用,给相应的接口增加in_place 参数来区分是否在原地触发。
ehds commented 3 years ago

参见评论,另外,需要补充一些单测

已经增加相关测试用例