【超详细】MIT 6.824 PartB 测试实验,根据 LOG 逐条分析。

PartB 测试实验代码

        位于raft目录下的test_test.go文件中,共有十个测试函数。

9. TestBackupPartB

测试目的:

测试领导者如何在面对日志冲突时迅速回滚,并确保日志能够正确复制到追赶中的节点。

关键步骤:

1、一共有3个raft节点,s0 - s2。

2、初始阶段随机选取一个Leader。

3、断开领导者,向断开的这位领导者提交多个命令,这些命令由于leader与另外两个follower失去连接,因此无法apply到状态机上。

4、等待一段时间后,另外两个机器会重新开始选举过程,并向新领导者提交多个命令。
5、测试新领导者如何处理提交失败的命令,并确保日志复制到新的追随者。
6、最后,恢复所有节点的连接,验证日志一致性。

日志分析:

1- 2、三个raft节点随机选取一个leader

000004 T0000 VOTE S0 Follower->Candidate, For T1
000005 T0000 VOTE S2 Follower->Candidate, For T1
000007 T0001 VOTE S2 -> S0, Reject voted, Already voted to S2
000007 T0000 LOG1 S1 Follower->Follower, For T0->T1

// s1 收到 s2 的心跳,先 align term,这时的term是相等,那么继续判断自己是否投票,如果还没有投票,就需要使用isMoreUpToDateLocked函数,对比双方的lastTerm和lastIndex,判断对方是否有资格成为Candidate。
000007 T0001 VOTE S1 Compare last log, Me: [0]T0, Candidate: [0]T0
000007 T0001 VOTE S1 -> S2, Vote granted
// s2 leader
000007 T0001 LEAD S2 Become Leader in T1

这个时候还没使用sfg提交命令,因此logs只有初始化时的一条日志。

000009 T0001 LOG1 S1 Follower->Follower, For T1->T1
000009 T0001 LOG2 S1 Follower accept logs: (0, 0]
000009 T0001 LOG1 S0 Candidate->Follower, For T1->T1
000009 T0001 LOG2 S0 Follower accept logs: (0, 0]
000009 T0001 DBUG S2 Match index after sort: [0 0 0], majority[1]=0
000010 T0001 DBUG S2 Match index after sort: [0 0 0], majority[1]=0

// leader s2 获得cfg的第一个命令
000515 T0001 LEAD S2 Leader accept log [1]T1

// 在心跳里向S1和S0发送存有命令的log,S1成功接收命令。

000714 T0001 LOG2 S1 Follower accept logs: (0, 1]

// s2 使用sort对matchIndex数组进行排序,将matchIndex数组的中位数与CommitIndex进行比较,来确定这时是否可以将这个命令apply到状态机上。
000714 T0001 DBUG S2 Match index after sort: [0 1 1], majority[1]=1

// 此时的commitIndex 为 0,matchIndex 的中位数为1,可以apply。

000714 T0001 APLY S2 Leader update the commit index 0->1

// S0成功接收命令。

000716 T0001 LOG2 S0 Follower accept logs: (0, 1]
000716 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1

// peer(s0、s1)都成功apply这个命令

001425 T0001 APLY S1 Apply log for [1, 1]
001427 T0001 LOG1 S0 Follower->Follower, For T1->T1
001427 T0001 LOG2 S0 Follower accept logs: (1, 1]
001427 T0001 APLY S0 Follower update the commit index 0->1
001428 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=
001428 T0001 APLY S0 Apply log for [1, 1]

这段时间cfg都没提交新的命令,leader s2 也会给其他peer发送心跳,心跳是不包含任何log信息的。

002127 T0001 LOG1 S1 Follower->Follower, For T1->T1
002127 T0001 LOG2 S1 Follower accept logs: (1, 1]
002127 T0001 LOG1 S0 Follower->Follower, For T1->T1
002127 T0001 LOG2 S0 Follower accept logs: (1, 1]
002127 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
002139 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
002838 T0001 LOG1 S1 Follower->Follower, For T1->T1
002838 T0001 LOG1 S0 Follower->Follower, For T1->T1
002838 T0001 LOG2 S0 Follower accept logs: (1, 1]
002838 T0001 LOG2 S1 Follower accept logs: (1, 1]
002842 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
002842 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
003545 T0001 LOG1 S1 Follower->Follower, For T1->T1
003545 T0001 LOG1 S0 Follower->Follower, For T1->T1
003545 T0001 LOG2 S0 Follower accept logs: (1, 1]
003546 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
003545 T0001 LOG2 S1 Follower accept logs: (1, 1]
003546 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
004262 T0001 LOG1 S0 Follower->Follower, For T1->T1
004262 T0001 LOG2 S0 Follower accept logs: (1, 1]
004263 T0001 DBUG S2 Match index after sort: [1 1 1], majority[1]=1
004265 T0001 LOG1 S1 Follower->Follower, For T1->T1

// s2 获得cfg后续的三个命令
006733 T0001 LEAD S2 Leader accept log [2]T1
006734 T0001 LEAD S2 Leader accept log [3]T1
006734 T0001 LEAD S2 Leader accept log [4]T1

// 之后s2失去和其他节点的连接,s1超时成为Candidate

010107 T0001 VOTE S1 Follower->Candidate, For T2

// s0 向 s1 投票

010112 T0001 LOG1 S0 Follower->Follower, For T1->T2
010112 T0002 VOTE S0 Compare last log, Me: [1]T1, Candidate: [1]T1
010112 T0002 VOTE S0 -> S1, Vote granted

// s1 成为新的leader,这时会重置nextIndex[peer] = len(rf.log)  matchIndex[peer] = 0
010114 T0002 LEAD S1 Become Leader in T2
010141 T0002 LOG1 S0 Follower->Follower, For T2->T2

// s1 向 s0 发送心跳,同步日志。
010146 T0002 LOG2 S0 Follower accept logs: (1, 1]
010154 T0002 DBUG S1 Match index after sort: [0 1 1], majority[1]=1

// s1 获得cfg的第二个命令
010279 T0002 LEAD S1 Leader accept log [2]T2

// s1 和 s0 都 apply了cfg的第二个命令

010825 T0002 LOG1 S0 Follower->Follower, For T2->T2
010828 T0002 LOG2 S0 Follower accept logs: (1, 2]
010830 T0002 DBUG S1 Match index after sort: [0 2 2], majority[1]=2
010834 T0002 APLY S1 Leader update the commit index 1->2
010838 T0002 APLY S1 Apply log for [2, 2]
011532 T0002 LOG1 S0 Follower->Follower, For T2->T2
011533 T0002 LOG2 S0 Follower accept logs: (2, 2]
011533 T0002 APLY S0 Follower update the commit index 1->2
011534 T0002 APLY S0 Apply log for [2, 2]

// s2 因为失去了连接,它仍然认为自己是领导,继续收到cfg的第五条命令
016497 T0001 LEAD S2 Leader accept log [5]T1

// s2重新获得和其他节点的连接,它此时认为自己是leader,给s1和s0发送心跳,s0根据align term 拒绝s2的心跳。

016969 T0002 LOG2 S0 <- S2, Reject log, Higher term, T1<T2

// 也能收到s1 leader的心跳,发现自己term小,s2将变为follower
016970 T0001 LOG1 S2 Leader->Follower, For T1->T2

// 因为发心跳的时候是使用协程的,Lost这个结果是rpc发送心跳失败
017602 T0002 LOG1 S2 -> S0, Lost or crashed

// 这个是replication函数里的contextLost检查发现自己不是leader了。
017678 T0002 LOG1 S2 Lost Leader[1] to Follower[T2]

// s1 这时候失去和其他节点的连接,s2重新变为candidate
018486 T0002 VOTE S2 Follower->Candidate, For T3

// s0 收到 s2的心跳,term变为3

//。。。待续
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值