https://www.youtube.com/watch?v=vYp4LYbnnW8&feature=youtu.be
选一个server当leader
检测到crashes,就选个新的leader
Leader接受client请求,本地append log
leader将log复制到其他server(覆写不一致的地方)
保持logs是一致的
只有获得最新的logs的servers可以成为leader
初始化是Follower
(被动的,仅仅傻傻地等待心跳)
如果一直等不到,那就成为Candidate
。(发起RequestVote
RPCs,大家来投我当leader啊)
AppendEntries
RPCs: 复制我的log,发心跳来维持我的统治)只要发现更高的term
,我就乖乖变回follower。
current term
的值(但是都不知道全局的term是啥样,没有上帝视角)
成为Candidate
本地currentTerm++,自己给自己投一票
发送RequestVote RPCs给其他servers(超时重试上一步)
获得大多数支持:成为leader,发心跳。
收到leader的RPC,乖乖当follower。
每个server 每个term只投一票(持久化到硬盘)
赢得大多数选票才能赢得选举
选举超时: 是个在[T,2T]的随机数,如150-300ms
一般情况,有一个server会首先超时然后赢得选举
当T >> 广播时间的时候,工作良好
具体是ranking可能要考虑很多corner case
随机数的逻辑相对简单清晰
客户端发送command到leader
leader 本地append log
leader 发送 AppendEntries
RPCs给所有Followers
一旦有新的entry committed
AppendEntries
中通知Followers,哪些entries被committed如果followers 挂掉了或者反应迟钝
AppendEntries
直到成功常规情况下性能不错
每个log 都保存了term
什么叫committed?
大多数的机器都保存了一样的log。如同上图的committed entries
遇到这种奇怪的情况,Raft怎么解决呢?
目标:最小化special code来修复不一致
如果不同的servers 的log entries有一样的index 和 term
如果一个entry committed,所有前面的entries都被committed
AppendEntries
RPCs 包括了 前一个
entry的
Follower 必须包含matching entry,否则他会拒绝请求
induction step
,保证Log Matching Property
注意前提:leader的log永远正确
问题来了,我们怎么知道leader的log就一定正确呢?
一旦一个log entry committed,所有未来的leader都要保存这个entry。
servers如果没有完整的log,是不能被选举的
有个问题:按照前面的逻辑,如果S1先timeout,先发的RequestVote,S3后发,S2,S4,S5都干不过S1,都会同意让S1当老大,那S3不就当不了老大了?
Replicated And Fault Tolerant的缩写
复制的,容错的
Raft代表木筏:可以帮助你躲过Paxos这个万恶的大山