ratis是raft协议java版本的开源实现项目,位于Apache项目下。项目git地址:https://github.com/apache/ratis。raft协议是基于日志的强领导模型的共识算法。leader选举、集群数据同步都离不离开日志。ratis最终目的是为了实现分布式系统的高可用性,对于具体的应用程序,ratis使用状态机(StateMachineUpdater)对具体的应用程序抽象隔离,保证ratis实现raft协议的纯粹性和可移植性。
1、Ratis结构梳理
1、raft协议
2、mutli-raft协议
2、ratis正常工作模型
客户端向raftServerImpl提交请求,请求最终由 RaftLog、LogAppender、LeaderState、StateMachineUpdater、StateMachine共同完成。具体步骤如下:
1、客户端向RaftServerImpl发送请求
2、RaftServerImpl将请求发送给RaftLog,构建日志并写入日志文件。
3、RaftServerImpl将请求提交给LeaderState(返回一个CompelableFuture),等待请求处理完成。
4、LogAppender检测到新增日志,复制日志到对应的Follower节点,并等待节点的响应。
5、LogAppender接收到Follower节点日志提交成功响应后,将日志发送给LeaderState提交。
6、LeaderState检测到大所属节点都已经同步成功后,提交日志,并通知StateMachineUpdater服务
7、StateMachineUpdater服务检测到新提交的日志,读取日志并发送给StateMachine(应用程序通过该步骤接收到客户请求)并处理日志。
8、StateMachine处理完成提交的日志,将对应日志在LeaderState中的CompletableFuture状态更新为完成。
9、RaftServerImpl通过CompletableFuture接收到处理结果,并返回给客户端。
3、ratis启动
ratis启动可以分解成三个部分:1、初始化;2、leader选举;3、启动leader;
1、初始化
初始化部分是指Ratis正常工作的必要模块的初始化和启动。其中就包括:1、RaftServerImpl的初始化;2、LifeCycle生命周期管理器初始化;3、StateMachineUpdater应用日志服务器的初始化和启动,以及作为初始角色Follower对应的服务FollowerState的初始化和启动。其中RaftServerImpl、LifeCycle、StateMachineUpdater不论节点属于什么角色,这三个服务都是必要服务。
启动顺序为:
1、有代理服务初始化LifeCycle生命周期控制器
2、构建RaftServerImpl服务实例,调用start方法启动该服务(这里的star并不是启动一个单独线程)
3、由RaftServerImpl初始节点角色管理服务,并将Follower作为初始角色启动(设置角色为:follower,启动角色对应的后台服务FoloowerState)。
4、设置集群为运行状态(更新LifeCycle的状态)
2、leader选举
ratis的leader选举是由Follower后台服务FollowerState触发,在指定的超时时间范围内没有接收到Leader心跳请求,就触发节点角色的变更(由Follower角色变更为 Candidate角色,并启动Candidate角色对应的后台服务LeaderElection),开启Raft 候选人的leader选举流程。
如1.2图:
第10步:指Follower角色对应的后台服务FollowerState在指定时间内没有接收到Leader的心跳信息,于是触发角色变更。
第11步:FollowerState -> RaftServerImpl#changeToCandidate指FollowerState通过Raft顶层服务RaftServerImpl变更节点角色,并结束当前服务(结束FollowerState服务)
第12步:RaftServerImpl -> RoleInfo#startLeaderElection指RaftServerImpl通知RoleInfo将节点角色变更为:Candidate
第13步:并启动leader选举(也就是Candidate角色对应的后台服务 - LeaderElection服务)
LeaderElection服务启动后,就开始向配置文件中配置的其它节点发送投票请求。正常清情况下投票请求分为两个阶段:
1、预选阶段 - Phase.PRE_VOTE
预选阶段抓哟是检查当前集群是否存在合法的leader,该步骤可以通过配置:raft.server.leaderelection.pre-vote 关闭该步骤。
2、竞选阶段 - Phase.ELECTION
竞选阶段就是正式leader竞选,candidate向各节点开始拉票,并在指定节时间内统计得到的投票情况。
3、leader启动
leader的启动由LeaderElection选举通过触发。如图1.2时序图所示:
第14步:由LeaderElection调用RaftServerImpl#changeToLeader,开启leader上位。
第15步:RaftServerImpl调用RoleInfo#shutDownElection,关闭LeaderElection后台服务。
第17步:RaftServerImpl调用RoleInfo#becomeLeader,将节点的角色设置为:leader,并初始化启动LeaderStateImpl。
第18步:LeaderState初始化并启动LogAppender,开启leader日志同步后台服务。
至此,Ratis服务leader上位就结束,可以开启正常的服务请求处理了。