sofastack / sofa-jraft

A production-grade java implementation of RAFT consensus algorithm.
https://www.sofastack.tech/projects/sofa-jraft/
Apache License 2.0
3.56k stars 1.14k forks source link

问一下logmanager reset主要是发生在什么场景 #979

Closed hanzhihua closed 1 year ago

hanzhihua commented 1 year ago

Your question

问一下logmanager reset主要是发生在什么场景,不太理解这个

Environment

fengjiachun commented 1 year ago

https://github.com/sofastack/sofa-jraft/blob/master/jraft-core/src/main/java/com/alipay/sofa/jraft/storage/LogStorage.java#L80

hanzhihua commented 1 year ago

看代码reset是发生在做完快照的时检查快照index的term跟日志进行比较不一致时做的动作。 如果是本地做快照,如果是第一次load的化,是不是日志跟快照不匹配,简单的删除存在日志是不是合理呢。如果后续做快照,理论上不应该出现这种情况,出现了应该是bug。 如果是远程copy 快照过来,也不应该出现这种情况,正常情况应该是term=0 另外reset这个操作不确定是不是合理,是不是直接交给上层处理,对raft协议了解不多,请指教,多谢

shihuili1218 commented 1 year ago
// term = 本地的term,来自本地快照或者log

if (term == 0) {
    // 。。。
} else if (term == meta.getLastIncludedTerm()) {
    // 本地term=snapshot的term,说明本节点没有落后太多,甚至可能在此之前本节点是leader,拥有一些不该存在的log,因此可能需要truncate
} else {
    // 本地term!=snapshot的term,可能本地term大于,也可能小于,都是允许的情况。
    // 如果大于(因为prevote的存在,这种情况应该不存在),在此之前本节点是leader,提出一些日志,未达成共识。
    // 如果小于,在此之前本节点也可能是leader,提出一些日志后,宕机了很久,恢复过来后,它应该以当前leader为准。
    if (!reset(meta.getLastIncludedIndex() + 1)) {
    }
}
hanzhihua commented 1 year ago

理解,reset方法只出现在从leader copy 快照过来,而且跟本地日志有冲突,如你举的场景。 我有一个不成熟建议,其实在jraft中有很多这样的方法,只会出现在特点的场景,如这个reset,还有checkAndResolveConflict方法中,firstLogEntry.getId().getIndex() == 0只出现leader中,不等于0是follower中,是不是可以加上一个Requires限制,可以快速发现问题。

因为我早期使用jraft时候,就出现了firstLogEntry.getId().getIndex() != 0 出现leader中,主要原因是raft 线程池满了出错了(线程主要用在rpc中同步中)