Raft协议介绍

   Raft是一个分布式协议,现在随着用户的增多一台机器来运算后台数据已经不足及支撑当前软件后端的运算量,所以就有了分布式的概念,可是分布式中有一个最大的问题就是他的高可用性,或者说高一致性,比如说我现在有一张银行卡卡里有余额一千元,然后现在在一台atm机上取钱,这时候我们访问了银行后台的一台服务器,atm吐出了五百元给我,这时候服务器后台的数据我的卡内余额应该是五百元,但是由于银行有很多台服务器,其中一台受理了我的请求和数据,这时候他怎么将我的操作通知到其他服务器,如果没有安全合理快速的方式的话,取完我再次去取钱卡这时候访问的是另一台服务器,我的余额可能显示的还是一千元....这就存在很大的隐患,那到底怎么才能让某台机器上的一个操作同步到所有的机器上,这就有是我们要介绍的分布式协议。最初的时候分布式协议里有个Paxos协议,这个协议实现了分布式机器之间的一致性但是这个协议是出了名的难懂,Raft的作者也曾公开说过,自己也是被Paxos虐了很多遍,所以才设计了一个和Paxos相似,但是通俗易懂的Raft协议。在功能上Raft完全可以替代Paxos协议。

  两者最大的区别就在于Paxos有一个基本通信协议,这个协议有很强的数据一致性,所以即使在Paxos集群中有多个leader的情况下,Paxos依然可以正常工作,这也正是Paxos的复杂之处,但是Raft则采用了完全相反的概念,Raft在设计的时候认为之可能存在一个集群leader,Raft针对一个leader的leader选举协议进行了详细的设计,这样在广播协议上就不用花费太大的功夫。接下来我们就介绍一个Raft的leader的选举协议。leader就是集群中的老大, 听他的!和他保持一致!

  先说Raft的日志广播过程,因为Raft中这个过程设计的十分简单,在集群中由leader进行日志广播,将日志数据发送给follower,follower对自己收到的日志进行应答,如果有超过一半以上的follower应答了leader当前发送的数据,那leader就会通知follower日志广播成功,这里的日志并非狭义的日志,在Raft中将用户数据叫做日志,在集群的所有节点上都有一个存储日志的队列,并且这个队列中的所有数据都有一个序号,并且这个序号是递增并且不空缺的,也就是连续递增的,在这个队列中有一个重要的数据就是Commit index叫做日志的提交位置,这个位置将日志队列分为了两部分,一部分是已经提交的日志,一部分是未提交的日志,已经提交的日志是刚刚我们说到的超过半数以上机器收到并且确认的日志,这些数据是可以给客户端来进行读取和使用的,而另一部分就是未提交的日志,也就是leader将日志下发了,但是还没又下发日志广播成功的通知。当节点收到日志之后会依次编号并且放在队列中,等待leader将commit index更新过来之后follower才会更新自己的commit leader,在日志队列中,已经提交的日志是不可改变的。不存在回退的情况。

   接下来我们就介绍Raft中的leader选举的协议。正是因为这个协议才保证了Raft中只有一个leader让Raft协议变得简单易懂,除去保证同时只有一个leader之外,还保证只有leader可以往follow发送数据,不可以由follow往leader发送数据。在Raft中的leader采用多数派协议,也就是说只有大多数人同意你成为leader你才可以成为leader,支持你的人必须超过半数,这样的话就保证了同时只能存在一个leader。当一个leader失去链接一段时间之后,这个链接是由心跳包来保证的,candidate会发送投票请求,由fallower进行投票,如果超过半数的人给他投票的话,那他就是新的leader开始进行广播leader。但是这时候也会存在一种情况,就是超时机制。首先每个follower的leader超时时间是随机的,也就是说如果说真的是leader出现了情况,这时候在一秒之后a发现了leader断开了,而b可能两秒钟才能意识到,c则可能是三秒才意识到。这 时候不同的机器意识到leader的时间不同,那他们去竞选成为leader的时间也就会存在差异。这样就在一定程度上避免了同时多个candidate竞选成为leader的情况,不过这里的时间都是在一定范围内的随机出来的,不能差距太大。并且还有一层保护机制,就是当每个candidate选举成为leader如果在一定时间内,没有leader产生,就会重新发起选举,各个candidate的重新选举时间也是随机的。这样就会避免多个candidate又同时进行竞选leader。时间同样不能过大或者过小,过大的话影响程序的平滑运行,超时间没有leader,太小的话很容易引起冲突。

  但是仅有这些是远远不够的,那什么样的节点才可以成为candidate去竞选leader,那什么样candidate follower会给他投票呢?首先candidate的日志节点的长度要等于或者超过一半以上的follower节点。因为follower节点众多,当一个leader发生故障的时候follwer中的日志情况很大可能是不相同的,有的多有的少,并且commit index 也是可能不相同的。已经提交过的日志是保证不能丢失的,不然这个协议的用处也就没有了,所以已经提交的日志是必须复制到所有节点上的。所以Raft就对candidate进行了规定只有已经包含了所有已经提交的节点才能成为candidate,实现也是十分的简单,当leader发生故障之后,candidate会发送自己的竞选请求,在请求中包含了自己当前的日志长度,说到投票请求的follower会和自己对比candidate的日志长度,只有candidate的日志长度等于或者长于自己的日志长度,follower才会对他进行投票,如果有超过半数的follower对他进行了投票那他就变成了新的leader。注意这里检查的是日志的长度并不是说去检查commit index为什么呢?因为比如说leader的日志是12345,然后commit index是4也就是说已提交的日志是1234,但是follwer或者说candidate的a的日志是123并且全都提交了,b的日志是12345但是提交的只有123,也就是说在leader看来4应该已经被提交了,但是当超过半数的时候他就认为已经被提交了很有可能还存在少半部分的节点不包含这个节点,这时候如果比较commit index 的话ab两个节点是一样的,因为他们都是只提交了123三个节点,但是如果选举a为leader的话日志4和5就会丢失,如果b当选的话他会从4开始再次进行广播就不会丢失4,5日志数据,所以在选举的时候必须是日志的长度而不是提交的日志长度,当candidate当选为leader之后会将自己的所有日志进行同步。

  并且可能是存在一些情况,比如leader因为网络情况故障了,但是在这段时间内选出来了新的leader,不过这时候旧的leader又再次恢复了链接,这时候他是不知道自己已经被取代了还是向大家发送数据,Raft并不能让这个旧的leader不发送消息,但是他会让follower拒绝旧的leader的数据,leader向follow发送数据的时候并不是只有简单数据,他还包含了一个term值,term是指从一次leader选举开始到下一次leader选举的时间,这段时间只能有一个leader被选举成功,当follwer收到日志之后会检查term号码。如果发送数据来的leader的term号码大于等于自己的号码,那就接受他来的数据,如果不是那就拒绝这个leader发送来的数据,说明他已经是一个旧的leader,这时候他还会给旧的leader发送自己当前新的term数据。当旧的leader收到了大于自己的term编号,他就知道自己已经过期了不再是leader了就将自己变成一个follower。

  这是一篇对于Raft协议的简单介绍。

你可能感兴趣的:(实习)