当前位置: 首页 > 科技观察

图解分布式共识算法_0

时间:2023-03-18 22:00:58 科技观察

今天的文章,我们将通过图解的方式深入学习和理解分布式共识的原理。开头先问灵魂:什么是分布式一致性?您的应用程序是单个节点吗?您的系统用户多,是否支持扩容?系统是否使用Raft、Paxos?……看懂不看没关系。后面会开始我们的例子,通过图的方式来描述一致性的工作原理。1.前奏假设我们有一个系统。它是一个单节点系统,只部署在一个实例上。可以理解为一个数据库服务(DatabaseServer),实例上只有一个数据X,我们后面的故事会围绕改变X的值展开。我们还有一个客户端(Client),需要写入数据到节点(服务器)。这时候应用代码写起来也简单了,这个数据的一致性也容易保证。写请求执行完后,客户端和服务端的X数据都变成了8。用户量少的时候,我还在担心什么时候每天有几百万用户。当用户数量增加一点时,我发现原来的实例无法处理。此时为了支持更多的用户访问,扩展了更多的实例。那么问题来了,当我们有多个实例节点时,客户端向其中一个节点写入数据,如何同步到其他节点呢?如何保证节点间数据的一致性?这就是分布式的一致性问题。2.Raft协议概述Raft是解决上述分布式共识问题的协议。类似的协议还有Paxos、Zab等,Raft比Paxos更容易理解和实现。这次我们将忽略Raft以了解它是如何工作的。在Raft中,一个节点可能有三种状态:FollowerCandidateLeader在下图中的内容中,以上三种状态分别对应以下三幅图。在任何时候,它只会处于以上三种状态之一。最初,所有节点都处于Follower状态。如果follower节点不能再接收到leader节点的消息,它们的状态就会变为Candidate。候选节点向其他节点发起投票请求,其他节点响应投票。如果获得大多数节点的投票,Candidate节点将成为Leader。上述过程就是分布式共识协议中的“LeaderElection”。系统的所有后续更改都是通过Leader进行的。然后通过Leader到达其他节点。每次客户端的变更请求到达领导者时,都会被视为一个Entry,首先被添加到节点的日志(Log)中。这个新的日志条目还没有被提交,所以节点中X的值不会被更新。领导者首先将日志条目复制到所有跟随者节点。然后,领导者等待,直到大多数节点都写入了该条目。Leader节点收到大部分节点的writeresponse后,会提交entry,此时leader节点的值变为5,然后leader会通知follower节点自己的entry已经提交。此时,每个follower节点也会提交之前收到的entry。整个系统的所有集群节点都达到了一致的状态。这个过程一般称为日志复制(LogReplication)。3、LeaderElectionRaft中有一项控制选举的超时设置。选举超时时间是追随者成为候选人的等待时间。该值是介于150毫秒和300毫秒之间的随机值。选举超时后,follower将成为候选人开始新的选举周期(term),同时投票给自己。并向其他节点发送请求投票的消息。如果收到消息的节点在此期间没有投票,则需要投票给candidate,节点重置自己的选举超时时间。如果候选人获得大多数节点的选票,它就成为领导者。此时leader会在心跳检测期间向所有follower发送AppendEntries消息。检测频率由心跳超时设置。然后每个follower也会发送一个对AppendEntries消息的响应。这个选举周期会一直持续到一个follower停止接收心跳消息并成为candidate为止。让leader停下来看看连任的情况。此时节点B已经停止,所以节点A和节点C都收不到心跳报文。前面我们说过,如果没有收到心跳消息,节点的状态就会从Follower变成Candidate,所以A和C会在各自的选举超时设置内改变自己的状态。此时节点A和节点C都在等待,因为节点C先超时,所以会先开始一轮选举。和上面的选举流程一样,先添加一个Term,给自己投票,然后向其他节点发送投票请求。在收到节点A的投票后,节点C现在被提升为term2的领导者。我们总是说“大多数选票”(amajorityofvotes)。这样可以确保在一个投票周期中只会产生一个领导者。假设两个节点同时从Follower变为Candidate,此时都将升级Term,并请求其他节点不要给自己投票。此时,两者的用语其实是一样的。在同一任期内,其他节点只会投一票,所以每个候选人只会收到一个节点的一票。因为不超过“多数”,就不能成为领导者。这些节点将等待新一轮的选举。此时节点D最先开始投票,获得了大部分的选票,最终在Term5成为了leader。4.LogReplication选出leader后,需要将所有的变更信息复制到系统中的所有节点。这些是通过与心跳检测相同的附加条目消息完成的。让我们来看看这个过程。最初,客户端向领导者发送更改。这个变化会被添加到领导者的日志中,并在下次心跳检测时发送给跟随者。当follower收到消息后,会向leader发送一个响应ack消息。leader在收到大部分follower响应后,提交条目并向client发送响应。并在下一次心跳时,通知跟随者执行提交操作。follower在写入完成后向leader发送响应。此时client再次向leader发送消息,需要对X进行加2操作,leader将消息添加到日志后,向各个follower发送心跳。关注者在收到回复后继续回复。leader收到ack后,确认本次执行的commit,然后向client发回响应。在下一次心跳时,将写入发送给每个关注者。此时我们系统中的X变成了7,各个节点的数据保持一致。5.什么是“多数”?我们在之前的很多场景中都提到了“最”。大多数是多少?例如,我们需要大多数关注者在选举和日志复制期间发回响应消息。这里的大多数和我们日常生活中的基本一样,也就是一半以上。比如一共有5个节点。此时,一名候选人成为领导者。在投票过程中,必须至少收到3票。官网有动画可以自定义互动时间,感兴趣的朋友可以自行查看。【本文为专栏作家“侯书城”原创稿件,转载请通过作者微信公众号“Tomcat物语”获得授权】点此查看本作者更多好文