raft 5.3 Log replication

2021-02-08  本文已影响0人  YourFoot

Raft 笔记

5.3 Log replication

要保证:

  1. 如果不同日志中两个entry有同样的index和term, 那么储存的是同一个指令

    Leader 一次只创建一entry

  2. 如果两个不同日志中两个entry有同样的index和term, 那么两个entries之前的记录都是一样的

    通过Leader发送AppendEntries给各个follower来检查是否和Leader的log一致,如果不一致,Follower就拒绝(拒绝后操作:Leader处理不一致)

    理想情况,Leader和Follower的状态是一样的,但是可能遇到上一个Leader没有复制所有的entries到日志中,或者Leader崩溃,没来得及commit log

Leader处理不一致:

当Follower和Leader的日志不一致时,Leader强制抹除Follower的日志内容并将自己的日志内容复制给Follower(Leader's log == Fowllower's log).

Leader发送AppendEntries 给 Follower 来找到最新的已经committed了的entry,然后少了entries的添上,多了的entries删除.

对于每个Follower,Leader会维护一个 nextIndex :index of next log entry the leader will send to that follower

当Leader第一次启动(包括更换leader),所有的nextIndex设置为Leader log 的下一个index. 上面图中是 11

Screen Shot 2021-02-07 at 3.44.44 PM.png

如果Follower's log和leader不一致,那么下一个AppendEntry就会失败。Follower返回rejection,nextIndex--

上图b和leader的情况:

1.nextIndex是11,sendAppendEntries到b, 发现index 11没有指令,nextIndex减一并返回false,一直减到5然后发现index=4 term = 4匹配Leader的index=4,term=4, 返回true, matchIndex is 4,nextIndex是5。

2.Leader此时知道4是对的,将5的指令发送给b, b index = 5 填上4.

5.4 Safety

前面的一些机制并不能完全保证每个状态机执行的是相同的指令。比如,当Leader提交的时候,其中一个follower可能不能用了,就会commit失败,然后它被选成了新的Leader,这时候之前应该提交的entries可能被新的entries取代。结果就是,不同的状态机执行了不同的command sequence.

5.4.1 Election restriction

Raft在选取新的Leader的时候会检查candidate是不是拥有所有的committed entries,如果没有就阻止它成为Leader: 通过RequestVote RPC实现: RPC拥有candidate的log信息。

当Follower投票时, 它会拒绝投票如果它的log比candidate的更新(拥有的committed entries更多)

5.4.2 Committing entries from previous terms

不能简单的通过count大多数entries的方式提交之前term的entry。例如:在(c)中,index2 中的2是大多数,但是(c)不能因为这个就commit 2. 可能出现(d)和 (e)两种情况

(d)中,S5成为Leader后,由于自己的值3拥有比2更大的term,导致用值3将已经commit的2覆盖,所以之前2是不能commit的

下图描述了当一个old entry储存在大部分servers上 依然存在被未来新的Leader重写的可能。

Screen Shot 2021-01-31 at 6.43.58 PM.png

解决上述问题:

因此Raft限制只能通过判断大多数的方式提交当前term的entry,进而对之前的entry间接提交,如过程e所示

上一篇下一篇

猜你喜欢

热点阅读