PikaLabs/floyd

Why commit index would be persistent?

Opened this issue · 8 comments

Maybe the commit index shouldn't be persistent in RaftMeta, instead, it will be set correctly by new leader after the first log entry being appended on quorum.

👍

确实论文里面描述commit_index和last_applied好像都没有持久化;还有, last_log_index是不是也不需要持久化?读取entry的时候,最后一条entry的index应该就是last_log_index?谢谢

@peacedog123 是这样的,理论上只需要持久化三个东西,term、当前term给谁投过票、所有Log

commit index,不需要持久化,因为用peer回复的last index来重新计算,floyd目前还是持久化了这个,未来可以看有没有必要去掉

applied index 不需要持久化,是由于幂等,可以从snapshot的位置开始重放,以后有了trim和snapshot功能可以去掉

last_log_index当前也没有单独持久化,就是Log的最后一个

@CatKang 谢谢哈

是我没看仔细,还不太熟悉rocksdb的接口,刚又看了一眼,last_log_index确实就是最后一条entry的key
if (it->Valid()) {
last_log_index_ = BitStrToUint(it->key().ToString());
}

从正确性的角度来看,现在是不是就是缺少 LEADER获得大多数选票以后的NO-OP消息的逻辑?有个问题没想明白的是,在获得大多数投票和NO-OP消息commit这段时间内,LEADER是不是不能对外提供服务的?谢谢

@peacedog123
标准的raft应该是不需要成为leader后的no-op的,我们会在成为leader后触发一次heartbeat,这个是为了尽快将新Leader信息告知其他Peer,避免无效的抖动。

我猜测你说的是这段内容:

[8 Client interaction] Raft handles this by having each leader com- mit a blank no-op entry into the log at the start of its term.

这个地方是在讲,为了优化读,希望能Leader本地处理只读请求,因此需要给Leader加Lease。这带来一个问题是新Leader并不知道自己哪些数据是commit的,因此需要强行提交一个no-op,之后才能提供读服务
floyd没有这个问题因为实现的是标准raft,所有的读都会写log,走完整的一致性过程

@CatKang 多谢,这下明白了,确实是看到了这里。一直被raft里面“Raft never commits log entries from previous terms by counting replicas.”这个保证所限制。如果所有的读也会有log记录的话,那这样一致性应该没问题了. 不过,这样的话如果读多写少的系统,是不是日志量就增大了?这样log compaction和snapshot的功能就必须加上了. Raft论文里面好像日志都是write的entry, 还以为不会有read的entry, 多谢指点!

@peacedog123 恩是的,这个log compaction和snapshot也是floyd接下来需要加的。另外关于“Raft never commits log entries from previous terms by counting replicas.”之前写过篇文章分析,自认为还比较清晰,可以参考下:https://zhuanlan.zhihu.com/p/31609030

@CatKang 好的多谢, 去拜读下 :)