首页 > 编程语言 >分布式一致性算法——Raft

分布式一致性算法——Raft

时间:2023-09-18 15:12:04浏览次数:45  
标签:结点 Log Candidate Follower 一致性 Raft Leader 分布式

Raft Leader Election

背景介绍

Raft是一种用于管理Log的分布式一致性算法,在了解Raft之前首先需要了解为什么需要Log?

对于不同的系统,无论是中间件疑惑是其余的系统,我们如果想要求其满足CAP协议中的一致性,需要尽量保证多节点的数据是相同的,也就是所谓的“共识”。下文中将这些需要保证一致性的系统的每个结点称为Node。

但这里存在一个问题,就是Node本身的复杂性是很高的,如果想要将整个Node的所有状态进行一个持久化,代价是巨大的。因此,采用了“复制状态机”的办法,原文定义如下:

If two identical, deterministic processes begin in the same state and get the same inputs in the same order, they will produce the same output and end in the same state.

实际上就是相同的初始状态+相同的操作=相同的结果。因此,就我们需要记录结点的操作记录,即Log。

采用这种方式问题就简化了,我们只需要保证Log的准确传输以及保证顺序性,就可以达成我们想要的效果。“复制状态机”基本模式如下图:

接下来我们考虑如下一个模型:对于一个系统集群,其有一个Leader和多个Follower,其中Leader负责接收和处理Client的请求,并将数据同步至Follower,Follower不处理任何请求,仅负责数据存储,当Leader崩溃时可以随时转变为Leader进行接替。

进而简单解释该图:

  1. 当Client向服务器集群发起请求,请求操作数据时,此时操作命令为A,Leader接收到请求,将A转化为对应Log,LA
  2. 共识模块将LA分发至各个Follower,要求Follower进行保存
  3. 待Follower将LA保存完毕后,告知Leader,Leader将LA转变为对应操作,应用于数据
  4. 待数据修改后,将修改结果发送给Client

这里的共识模块就是各种分布式一致性协议的具体实现,Raft是其中一种。现阶段使用Raft的中间件有很多,例如Kafka、etcd等。这里我们主要介绍Raft。在介绍Raft的选举机制前,需要有一定的前置知识。

前置知识讲解

1. Term(任期)

故名思意,Term即一个Leader本身执行其Leader工作的一段时间,当发生某种情况,导致当前Leader无法正确工作,则就要开始下一个Term。

需要注意的是,一个Term是从Leader选举开始,到当前Leader“卸任”为止。事实上Term仅仅是一个递增的数字,但在Raft算法中却起到了逻辑时钟的作用,因为Raft本身很多机制都与随机性有关。

2. Leader、Follower、Candidate

在Raft算法中,一个结点的任意时刻只能是如下三种状态的一种:

  1. Leader
  2. Follower
  3. Candidate

Leader和Follower已经做过简单的介绍了,对于Candidate,如果Leader无法正常工作,或者Follower认为Leader无法正常工作,此时结点会开始进行重新选举,而重新选举之前,需要将自己设置为Candidate状态,选举成功后,再重新转换为Leader或者Follower。

以下是三种状态的转换图,后面会进行详细讲解:

3. Raft与前文介绍的区别

如果真实世界真的能保证每个Leader发出的请求,Follower都能立刻接收到并且做出正确操作,进而返回,那肯定是最好了,但是,事实并非如此。如果能做到这种情况,就是保证了真正的强一致性。

Raft保证的是最终一致性,即理论上到达某一个时间点,系统会达到正确的一致性的效果。因此,对于前文的第3步,Raft要求,只需要大部分的Follower保存了Log就可以了。当满足分布式算法的保存条件时,证明Leader可以安全地修改本地数据了,这称为该Log已经Commit。

注意:对于Follower没有成功存储的Log,Leader在Commit后会一直进行重传,直到Follower接受为止,因此,Log是永远有序的。

事实上,在Leader和Follower中,都要保存Log数据,形态如下图:

这是一个Leader和它的Follower a-f的日志保存状态。其中的数字代表的是该日志所在的任期。并且每个日志有自己独特的Index。也正因为Log的有序性,导致日志有如下特性:

  1. 如果在不同的结点上的两条日志,但是其Term和Index相同,那么两条日志记录的命令相同
  2. 如果在不同的结点上的两条日志,其Term和Index相同,那么他们之前的日志也都相同。

了解了这些之后,就可以介绍Raft的Leader选举了。

Raft的Leader选举

成为Leader的条件

事实上,Raft选取Leader的条件只有一个:被选取的Leader需要得到大多数结点的承认,这个大多数就是至少大于等于n/2上取整,n为总结点数

那么其他结点承认该结点的条件是什么呢?想要得到其他结点的承认需要满足:条件:Candidate结点的Term必须要>=选举者的Term,其次Candidate结点的Index也要>=选举者Log的最大Index。这就意味着满足结果:Candidate需要携带上一个Term的所有Commit的日志才能被选中

为什么说满足了条件就满足了结果呢?

因为要成为Leader有一个隐藏条件,就是需要得到大部分结点的承认。Commit的条件是大部分结点保存了Log就可以Commit了。而Candidate的Log如果Index >= 选举结点,且Log的Term也大于等于选举结点,证明,选举结点的所有日志Candidate都已经保存好了。再加上要得到大部分结点的同意,从集群中任选(n/2上取整)个结点,必然有一个结点含有Commit的日志的全集,因此结果成立。

而新的Leader就要承担起补全其他Follower日志的工作,这一部分不属于Leader选举,这部分另一篇文章再讨论。

结点状态转换过程

最后,我们再看一下结点的状态转换图:

当结点启动时,初始状态是Follower,Leader为了保证能与Follower有效沟通,因此,与Follower之间会有一个心跳机制,即定时向Follower发送一个空请求,目的就是验证Follower是活着的。

但是,在Leader不存在时,Follower是无法接收到心跳的,因此,在多次无法接收到心跳时,我们称为time out,则此时要选出新的Leader。因此当前Follower就会自告奋勇,去竞选Leader,会执行如下操作:

  1. 将自己的Term ++
  2. 投自己一票
  3. 并行发送给其他Node,请求其他结点的承认
  4. 等待其他结点的回复结果

当结点BC接收到A的请求投票的请求后,会查看是否满足刚才谈到的条件,如果满足,就会投给A一票(注意:每个投票者只能最多给一个Candidate投票)。A接受到投票后,acknowledge会++,当接收到大多数结点的承认后,A就成为了新的Leader。然后A就会通知其他结点,告诉自己成为了新的Leader,防止有新的选举产生。当三类结点接收到这个广播消息后会采取如下操作:

  1. Candidate:由于已经选举处理新的Leader,因此转变为该Leader的Follower
  2. Leader:由于选举出了新的Leader,则将自己转化为新Leader的Follower
  3. Follower:发现了新的Leader,将自己转化为新Leader的Follower

最后,对于上面的状态机,我们会发现有一种特殊的情况,即选举超时。这种情况是怎么回事呢?由于如下原因:

  1. 每个投票者只能最多给一个Candidate投票,投票者的票是先到先得。
  2. 可能同时存在多个结点处于Candidate状态

因此,就可能出现如下情况:当前集群中有4个Node,其中两个Follower都发现了系统中找不到可用的Leader,因此转化为Candidate状态,请求其他结点承认。

由于A、D两者的票是投给自己的,如果B投给A,D投给C,那么就会产生如下情况:

那么就会存在A、D都没有获得大多数Node承认的情况,如果发生这种情况,就需要选举超时来处理,等待超时时间到达后,开始一个新的Term,重新进行选举。为了去避免出现多个Node同时进行选举,Raft采用了一个随机的election timeout来减缓这个问题。

结论

至此,我们分析完了Raft选举机制的内容,Leader是Raft协议运行的一个非常重要的模块,后面的文章会讨论Raft的Log Replication问题。

标签:结点,Log,Candidate,Follower,一致性,Raft,Leader,分布式
From: https://www.cnblogs.com/yanlishao/p/17711869.html

相关文章

  • 极速上手Python分布式爬虫
    随着互联网的快速发展,获取大量数据已成为许多项目的核心需求。而Python分布式爬虫是一种高效获取数据的方法。今天,我将个大家分享一下,想要极速上手Python分布式爬虫的一些知识,让你能够迅速掌握这一实用的技术。什么是分布式爬虫?分布式爬虫是一种利用多台机器协同工作的爬虫系统。它......
  • 分布式系统设计
    1.分布式系统组件---消息队列RocketMq(重要特性:事务消息,半事务机制首选方案,最终一致性,死信队列,补偿方案)2.分布式系统组件---消息队列Kafka3.高并发系统,提升QPS,提升并发能力利器----Redis集群高可用方案4.大型分布式数据库系统选型和研究--- TiDB......
  • 深入探讨Spring Cloud Config的分布式事件
    介绍SpringCloudConfig是一个分布式配置管理工具,它可以将应用程序的配置集中管理,并提供了RESTAPI和Web界面来访问这些配置。在分布式系统中,配置管理是非常重要的,因为它可以帮助我们快速地修改应用程序的配置,而不需要重新部署应用程序。在本文中,我们将深入探讨SpringCloudConf......
  • MySQL——分布式锁
    锁锁是一种抽象概念,是一种思想。并发环境下,多个线程会对同一资源争抢,可能导致数据不一致的问题。因此,很多编程语言都引入了锁。Java中的锁互斥锁(悲观锁(有锁同步))操作系统悲观地认为如果不严格同步线程调用,那么一定会产生异常,互斥锁将会将资源锁定,只供一个线程调用,阻塞其他线程(......
  • 分布式
    单机服务器常发生的问题在单机服务器中,常常会面临以下几个问题:服务器电脑宕机:这是最常见的问题之一,当服务器的硬件或者软件出现故障时,可能导致服务器无法正常运行。这种情况下,系统管理员需要及时排查故障原因,并修复问题,以保证服务器的稳定性和可用性。网络异常:网络连接是服......
  • 分布式数据库(背)
          ......
  • 分布式Broker模式介绍
    Broker模式定义了6类:Client,Server,Client_Proxy,Server_Proxy,Broker,Bridge。Server:责任:处理特定领域的问题,实现服务的细节,注册自己到Broker,处理请求并返回结果或异常。协作类:Server_Proxy,BrokerClient:Client是需要访问远程服务的应用程序,为此,Client发送请求到Broker,并从Broker上接收......
  • 分布式搜索引擎Elasticsearch(1)
    ES的倒排索引倒排索引是ES实现快速搜索功能的核心概念,而倒排索引的概念是基于正向索引而言的。那么什么是正向索引呢?正向索引就是先通过文件名找到具体的文件,再获取文件中的内容过程。mysql的查询功能就是正向索引的思想,mysql查询数据时会先根据ID查询记录,再从记录中获取相关字......
  • Metamorphosis分布式消息中间件
    一 简介1.1定义    Metamorphosis是淘宝开源的一个Java消息中间件。关于消息中间件,你应该听说过JMS(1)规范,以及一些开源实现,如ActiveMQ和HornetQ等。Metamorphosis也是其中之一。    Metamorphosis是一款完全的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台......
  • 分布式协议与算法 概要
    最近系统性的学习了分布式协议与算法,在此做个小小笔记。理论拜占庭将军问题拜占庭将军问题(ByzantineGeneralsProblem)是一个著名的分布式系统中的问题,用于探讨在存在故障节点或恶意行为的情况下如何进行可靠的信息传递和共识达成。问题描述如下:假设有一组拜占庭将军围绕一座......