未整理

Raft中的安全性可以用一句话来概括:

If a leader has decided that a log entry is committed, that entry will be present in the logs of all future leaders.

如何理解这句话?通俗一点的说就是以下两点

综上,就应该保证所有committed log存活在每任leader中。这样就保证了,在日志复制过程中,committed log不会被删除掉。

为了实现安全性,Raft在leader选举和对committed log的定义两方面进行了限制。

限制leader选举

一旦某个节点超时,它将自己状态切换为Candidate,执行RequestRPC去其他节点”拉票“。为了证明自己能够”胜任“leader,Candidate节点会在RequestRPC中带上自己的部分日志信息作为“证明“,这包括自己节点上最后一个log entry的index和term。收到RequestRPC的节点会把Candidate的日志信息和自己的做个一个对比(V表示RequestRPC接收方,C表示RequestRPC发送方):

只要满足上面任意一条,RequestRPC就会返回false,表明”拉票“失败。

然而这还不够,考虑下面这样一种情况:

屏幕快照 2019-09-11 上午11.29.44.png

当S1节点将index=3这个log复制到S3后,因为这个log已经复制到大多数节点上了,leader S1会认为这个log committed(注意这是错误的,马上会讲到),就在此时,S1宕机,S5超时并发起选举,按照上面的选举方法,S5可以成为leader。这种情况下,S5一旦开始log复制,它会把S2~S4中的index=3上的log覆盖掉,然而这写log是在上一任期中已经被S1确定为committed了。这造成了严重的日志丢失,为了解决这个问题,需要对log committed状态进行限制。

限制committed log

一个log entry要变成committed状态,必须满足下面两个条件:

屏幕快照 2019-09-11 上午11.44.44.png

有了这两个限制,在S1宕机前,只有index 3 4上的log都复制到大多数节点后,S1才会认为它们已经committed了,这样的话即使S1宕机,S5也不可能成为leader。