Nacos 源码分析 (四) 一致性实现 raft

先介绍下raft 选举算法

在Raft中,节点有三种角色:

Leader:负责接收客户端的请求
Candidate:用于选举Leader的一种角色
Follower:负责响应来自Leader或者Candidate的请求
选举分为两个阶段:
服务启动的时候
leader挂了的时候
所有节点启动的时候,都是follower状态。 如果在一段时间内如果没有收到leader的心跳(可能是没有leader,也可能是leader挂了),那么follower会变成Candidate。然后发起选举,选举之前,会增加term,这个term和zookeeper中的epoch的道理是一样的。
follower会投自己一票,并且给其他节点发送票据vote,等到其他节点回复
在这个过程中,可能出现几种情况
收到过半的票数通过,则成为leader
被告知其他节点已经成为leader,则自己切换成为follower
一段时间内没有收到过半的投票,则重新发起选举
约束条件在任一term中,单个节点最多只能投一票
选举的几种情况
第一种情况,赢得选举之后,leader会给所有节点发送消息,避免其他节点触发新的选举
第二种情况,比如有三个节点A B C。A B同时发起选举,而A的选举消息先到达C,C给A投了一票,当B的消息到达C时,已经不能满足上面提到的第一个约束,即C不会给B投票,而A和B显然都不会给对方投票。A胜出之后,会给B,C发心跳消息,节点B发现节点A的term不低于自己的term,知道有已经有Leader了,于是转换成follower
第三种情况, 没有任何节点获得majority投票,可能是平票的情况。加入总共有四个节点(A/B/C/D),Node C、Node D同时成为了candidate,但Node A投了NodeD一票,NodeB投了Node C一票,这就出现了平票 split vote的情况。这个时候大家都在等啊等,直到超时后重新发起选举。如果出现平票的情况,那么就延长了系统不可用的时间,因此raft引入了randomized election timeouts来尽量避免平票情况

节点共有3种状态 leader ,follower 和candidate

看raftCore的实现

publish方法

  • 如果当前的节点不是leader,则转发给leader节点处理
  • 如果是,则向所有节点发送onPublish

1.判断如果当前节点不是leader,则转发给leader处理

2.如果是leader,lock加锁,重入锁ReentrantLock实现

3.构建数据datum,然后调用onPublish发送

   3.1 校验数据datum的value不能为空

   3.2 校验当前节点必须是leader

   3.3 校验当前节点的term,不能小于local;小于认为是一个过期的publish

   3.4 调用raftStore.write进行数据持久化,继续调用fileChannel.write 写数据

   3.5 更新leader节点的term,增加1;然后调用raftStore.updateTerm 更新到本地文件

4. 然后获取所有的节点,调用异步http发送消息

5.本质是调用AsyncHttpClient发送请求,如果发送 返回成功,就返回0,失败返回1

6.最后调用unlock解锁

对于master选举

1.先判断节点是不是都准备好 ready

2.调用sendVote发送投票,修改节点状态为candidate,调用asyncHttpPost发送投票

  

   

发布了331 篇原创文章 · 获赞 1 · 访问量 3474

猜你喜欢

转载自blog.csdn.net/kuaipao19950507/article/details/104086629