MIT6.824 分布式系统实验 (4)

不论中间经过了多少个term,假设现在的leader是S1,旧leader是S3,S3重新加入集群的时候,首先S3肯定会降级为follower,如果S3可以立即被选举为leader,那么就可以视为S3没有发生过故障。S1会发送新条目给S3的时候,S3会进行不一致性检查,经过多次发送并尝试append条目,S1会令S3的log状态与自己的达成一致。

关于已经commit的log是否会丢失的进一步讨论

假设当前leader是S3。已知leader选举,当term一致的时候,只能给log长于自己的投选举票。那么只有log长于其中超过半数机器的机器可以成为leader。已知leader永远不会丢弃自己已有的log,那么存在于leader中的被commit的log肯定不会被丢弃。丢弃的情况只会是一条log被大多数机器记录,但leader没有记录。

假设该log的index是i1,term是t1。根据log append的连续性,S3至多接收到i1-1之后就没有接收到t1的其他任何log了。进一步地,由于i1被保留到了S3入选的term,因此t1之后的leader都有i1记录,因此S3至多接收到i1-1之后就再也没有收到到选举为止的其他任何log了。在这种情况下,还要保证经历了所有的term(才能term与其他选举者一致),即使之后的所有term都不再append条目到任何机器上,那也有大多数机器比S3多了i1这条log,S3不可能选举成功。推出矛盾,因此commit的log不会丢失。

【persist】

persist类是raft类中的一个成员。其作用应该是为了保存state信息和snapshot信息,state信息包括currentTerm,votedFor,log。只有这三者需要被持久化存储,log是唯一记录了应用程序状态的地方,其中存储的一系列操作是唯一能在断电重启之后用来重建应用程序状态的信息;votedfor和currenterm是为了保证每个任期最多只有一个leader。其他的状态,例如lastApplied和commitIndex都可以通过leader和follower之间的交流来重新获得。

MIT6.824 分布式系统实验

【snapshot】

每个server会自己创建自己的snapshot,也会接受并install leader发送的snapshot(这发生在日志同步的时候nextIndex<=ssLastshot时)。只有leader可以让其他server install自己的snapshot,这和只有leader可以让其他server appendEntries一样,因此,发送处理和接收处理之前都必须check发送方的leader身份,并且可以以此来代替加锁。

收到installSnapshot和收到AppendEntries类似,都需要有检查leader身份,确认自己follower身份和reset election timer等操作。将得到的snapshot发送到applyCh即可。

假死问题:由于网络原因导致的心跳超时,认为leader已死,但其实leader还活着。

脑裂问题:指的是分布式集群系统中由于网络故障等原因,选举出了两个leader,集群分裂成两个集群。出现脑裂问题的原因是分布式算法中没有考虑过半机制。脑裂问题对分布式系统是致命的,两个集群同时对外提供服务,会出现各种不一致问题,如果两个集群突然可以联通了,将不得不面对数据合并、数据冲突的解决等问题。

为了解决脑裂问题,通常有四种做法:

zookeeper和raft中使用的过半原则;

添加心跳线。集群中采取多种通信方式,防止一种通信方式失效导致集群中的节点无法通信,比如原来只有一条心跳线路,此时若断开,则判断对方已死亡,若有两条心跳线,一条断开,另一条仍然可以收发心跳,保证集群服务正常运行,备用线路与主线路可以互相监测,正常情况下备用线路为了节约资源而不起作。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpxsg.html