分布式系统面临的问题
1)通信异常
网络本身的不可靠性,因此每次网络通信都会伴随着网络不可用的风险(光纤、路由、DNS等硬件设备或系统的不 可用),都会导致最终分布式系统无法顺利进行一次网络通信,另外,即使分布式系统各节点之间的网络通信能够 正常执行,其延时也会大于单机操作,存在巨大的延时差别,也会影响消息的收发过程,因此消息丢失和消息延迟 变的非常普遍。
2)网络分区
网络之间出现了网络不连通,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分成了若干个 孤立的区域,分布式系统就会出现局部小集群,在极端情况下,这些小集群会独立完成原本需要整个分布式系统才 能完成的功能,包括数据的事务处理,这就对分布式一致性提出非常大的挑战。
3)节点故障
节点故障是分布式系统下另一个比较常见的问题,指的是组成分布式系统的服务器节点出现的宕机或"僵死"现象, 根据经验来说,每个节点都有可能出现故障,并且经常发生。
4)三态(成功、失败和超时)
分布式一致性
一致性概念
分布式数据一致性,指的是数据在多副本中存储时,各副本的数据始终都是一致的。
但是由于各种原因,我们不能保证各副本的数据时时刻刻都是一致的,因为多副本存储存在同步问题。我们没有办法保证可以同时更新所有机器中的数据。比如网络延迟,即便同时向各个机器发送更新请求,也不能保证请求被同时处理,并且处理时间一致。
一致性分类
1、强一致性
这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往 对系统的性能影响大。但是强一致性很难实现。
2、弱一致性
这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致, 但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态。
3、读写一致性
用户读取自己写入结果的一致性,保证用户永远能够第一时间看到自己更新的内容。 比如我们发一条朋友圈,朋友圈的内容是不是第一时间被朋友看见不重要,但是一定要显示在自己的列表上。
解决方案:
方案1:一种方案是对于一些特定的内容我们每次都去主库读取。 (问题主库压力大)
方案2:我们设置一个更新时间窗口,在刚刚更新的一段时间内,我们默认都从主库读取,过了这个窗口之后,我们会挑
选最近有过更新的从库进行读取
方案3:我们直接记录用户更新的时间戳,在请求的时候把这个时间戳带上,凡是最后更新时间小于这个时间戳的从库都
不予以响应。
4、单调读一致性
本次读到的数据不能比上次读到的旧。 由于主从节点更新数据的时间不一致,导致用户在不停地刷新的时候,有时候能刷出来,再次刷新之后会发现数据不见 了,再刷新又可能再刷出来,就好像遇见灵异事件一样 。
解决方案:
就是根据用户ID计算一个hash值,再通过hash值映射到机器。同一个用户不管怎么刷新,都只会被映射到同 一台机器上。这样就保证了不会读到其他从库的内容,带来用户体验不好的影响。
5、因果一致性
如果节点 A 在更新完某个数据后通知了节点 B,那么节点 B 之后对该数据的访问和修改都是基于 A 更新后 的值。于此同时,和节点 A 无因果关系的节点 C 的数据访问则没有这样的限制。
6、最终一致性
最终一致性是所有分布式一致性模型当中最弱的。可以认为是没有任何优化的“最”弱一致性,它的意思是说,我不考虑 所有的中间状态的影响,只保证当没有新的更新之后,经过一段时间之后,最终系统内所有副本的数据是正确的。 它最大程度上保证了系统的并发能力,也因此,在高并发的场景下,它也是使用最广的一致性模型。
分布式理论:CAP定理
CAP定义
一致性( Consistency ):
即更新操作成功并返回客户端后,所有节点在同一时间的数据完全一致,这就是分布式的一致性。
可用性( Availability ):
服务一直可用,而且是正常响应时间。好的可用性主要是指系统能够很好的为用户服务,不出现用户操作失败或者访问超时等用户体验不好的情况。
分区容错性( Partition Tolerance ):
分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性或可用性的服务 。
CAP定理只能三选二,不能同时满足
假设有一个系统如下:
有用户向N1发送了请求更改了数据,将数据库从V0更新成了V1。由于网络断开,所以N2数据库依然是V0,如果这个时候
有一个请求发给了N2,但是N2并没有办法可以直接给出最新的结果V1,这个时候该怎么办呢?
这个时候无法两种方法,一种是将错就错,将错误的V0数据返回给用户。第二种是阻塞等待,等待网络通信恢复,N2中
的数据更新之后再返回给用户。显然前者牺牲了一致性,后者牺牲了可用性。
这个例子虽然简单,但是说明的内容却很重要。在分布式系统当中,CAP三个特性我们是无法同时满足的,必然要舍弃一
个。三者舍弃一个,显然排列组合一共有三种可能。
1、舍弃可用性,保留一致性和分区容错性
一个系统保证了一致性和分区容错性,舍弃可用性。也就是说在极端情况下,允许出现系统无法访问的情况出现,这个
时候往往会牺牲用户体验,让用户保持等待,一直到系统数据一致了之后,再恢复服务。
2、舍弃一致性,保留可用性和分区容错性
这种是大部分的分布式系统的设计,保证高可用和分区容错,但是会牺牲一致性
3、舍弃分区容错性,保留一致性和可用性
如果要舍弃P,那么就是要舍弃分布式系统,CAP也就无从谈起了。可以说P是分布式系统的前提,所以这种情况是不存在
的。
分布式理论:BASE理论
BASE全称由 Basically Available(基本可用),Soft state(软状态),和 Eventually consistent(最终一致性) 组成。
BASE是对CAP中一致性和可用性权衡的结果,BASE理论的核心就是:即使无法做到强一致性,但每个应用都可以根据自身应用的特点,采用适当的方式来达到最终一致性。
Basically Available(基本可用)
基本可用是指在出现网络故障的时候,允许损失部分可用性(不等价于系统不可用)。以下是基本可用的例子:
1)响应时间的损失
正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出 现故障(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了1~2秒。
3)功能上的损失
在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单,但是到了促销时间,可能为了应对并发,保护购物系统的稳定性,部分用户会被引导到一个降级页面 。
Soft state(软状态)
相对于一致性,要求多个副本的数据都是一致的,这就是“硬状态”。
软状态是指: 允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同 节点的数据副本之间进行数据同步的过程中存在延迟。
Eventually consistent(最终一致性)
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此最终 一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。
分布式理论:一致性协议2PC
概念
2PC即两段提交协议,是将整个事务提交分成两个阶段(准备阶段( Prepare phase )、提交阶段( commit phase ))来完成, 2是指两个阶段,P是指准备阶段,C是指提交阶段。
在计算机中部分关系型数据库支持2PC协议,Oracle和MySQL数据库。 二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。
执行过程
成功执行事务提交流程
阶段一:
1、事务询问
协调者向各个参与者发出事务请求,询问各个参与者是否可以执行事务提交操作,并开始等待各参与者的回复。
2、执行事务
写本地的undo和redo。
3、各参与者向协调者反馈事务询问结果。
ACK 确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。
只有当所有参与者返回yes时,才会进行阶段二。
阶段二:
1、发送提交请求
协调者向所有参与者发送commit请求。
2、事务提交
参与者接收到commit请求后,会正式执行事务提交操作,并在完成事务提交之后释放所占用的所有资源。
3、反馈事务提交结果
完成事务提交操作,参与者向协调者发送Ack信息。
4、完成事务
事务协调者接收到所有参与者发送的Ack信息之后,完成事务操作。
中断事务
假设参与者中任何一个向协调者发送了No响应或者在等待超时之后,协调者无法接收到所有参与者返回的结果,那么就会中断事务。
阶段一:
1. 事务询问
协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
2. 执行事务 (写本地的Undo/Redo日志)
3. 各参与者向协调者反馈事务询问的响应
阶段二:
1. 发送回滚请求:
协调者向所有参与者发出 Rollback 请求。
2. 事务回滚:
参与者接收到 Rollback 请求后,会利用其在阶段一中记录的 Undo 信息来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源。
3. 反馈事务回滚结果:
参与者在完成事务回滚之后,向协调者发送 Ack 信息。
4. 中断事务:
协调者接收到所有参与者反馈的 Ack 信息后,完成事务中断。
2PC优缺点
1、优点
原理简单、实现方便
2、缺点
- 同步阻塞
二阶段提交协议存在最明显也是最大的一个问题就是同步阻塞,在二阶段提交的执行过程中,所有参与该事务操作 的逻辑都处于阻塞状态,也就是说,各个参与者在等待其他参与者响应的过程中,无法进行其他操作。这种同步阻 塞极大的限制了分布式系统的性能。
- 单点问题
协调者在整个二阶段提交过程中很重要,如果协调者在提交阶段出现问题,那么整个流程将无法运转,更重要的 是:其他参与者将会处于一直锁定事务资源的状态中,而无法继续完成事务操作。
- 存在数据不一致问题
假设当协调者向所有的参与者发送 commit 请求之后,发生了局部网络异常或者是协调者在尚未发送完所有 commit 请求之前自身发生了崩溃,导致最终只有部分参与者收到了 commit 请求。这将导致严重的数据不一致问 题。
- 过于保守
如果在二阶段提交的提交询问阶段中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应信息的话, 这时协调者只能依靠其自身的超时机制来判断是否需要中断事务,显然,这种策略过于保守。换句话说,二阶段提 交协议没有设计较为完善的容错机制,任意一个节点失败都会导致整个事务的失败。
分布式理论:一致性协议3PC
概念
3PC是2PC的改进版,将2PC的准备阶段一分为二,共形成了CanCommit、PreCommit、DoCommit三个阶段。
执行流程
CanCommit阶段
1、协调者向所有参与者发出包含事务内容的CanCommit请求,询问是否可以提交事务,并等待所有参与者答复。
2、参与者收到CanCommit请求后,如果认为可以执行事务操作,则反馈YES并进入预备状态,否则反馈NO。
PreCommit阶段
此阶段分两种情况:
1、所有参与者均反馈YES,即执行事务预提交。
2、任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务。
事务预提交:(所有参与者均反馈YES时)
1、协调者向所有参与者发出PreCommit请求,进入准备阶段。
2、参与者收到PreCommit请求后,执行事务操作,将Undo和Redo信息记入事务日志中(但不提交事务)。
3、各参与者向协调者反馈Ack响应或No响应,并等待最终指令。
中断事务:(任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈时)
1、协调者向所有参与者发出abort请求。
2、无论收到协调者发出的abort请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。
DoCommit阶段
此阶段也存在两种情况:
1、所有参与者均反馈Ack响应,即执行真正的事务提交。
2、任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务。
提交事务:(所有参与者均反馈Ack响应时)
1、如果协调者处于工作状态,则向所有参与者发出do Commit请求。
2、参与者收到do Commit请求后,会正式执行事务提交,并释放整个事务期间占用的资源。
3、各参与者向协调者反馈Ack完成的消息。
4、协调者收到所有参与者反馈的Ack消息后,即完成事务提交。
中断事务:(任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈时)
1、如果协调者处于工作状态,向所有参与者发出abort请求。
2、参与者使用阶段1中的Undo信息执行回滚操作,并释放整个事务期间占用的资源。
3、各参与者向协调者反馈Ack完成的消息。
4、协调者收到所有参与者反馈的Ack消息后,即完成事务中断。
入阶段三后,无论协调者出现问题,或者协调者与参与者网络出现问题,都会导致参与者无法接收到协调者发出的do Commit请求或abort请求。此时,参与者都会在等待超时之后,继续执行事务提交。
3PC的优缺点
优点:降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点问题,阶段3中协调者出现问题时,参与者会继续提交事务。
缺陷:脑裂问题依然存在,即在参与者收到PreCommit请求后等待最终指令,如果此时协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。
分布式理论:一致性算法Paxos
概念
Paxos 有点类似我们之前说的 2PC,3PC,但是解决了他们俩的各种硬伤。该算法在很多大厂都得到了工程实践,比如阿里的 OceanBase 的分布式数据库,底层就是使用的 paxos 算法。再比如 Google 的 chubby 分布式锁也是用的这个算法。可见该算法在分布式系统中的地位,甚至于,paxos 就是分布式一致性的代名词。
Paxos解决了什么问题
Paxos解决了一致性问题,什么是一致性( consensus )问题呢?
在一个分布式系统中,有一组的 process,每个 process 都可以提出一个 value,consensus 算法就是用来从这些 values 里选定一个最终 value。如果没有 value 被提出来,那么就没有 value 被选中;如果有1个 value 被选中,那么所有的 process 都应该被通知到。
我们假设一种情况,在一个集群环境中,要求所有机器上的状态是一致的,其中有2台机器想修改某个状态,机器 A 想把状态改为 A,机器 B 想把状态改为 B,那么到底听谁的呢?
有人说,可以像 2PC,3PC 一样引入一个协调者,谁先到,听谁的。
但是如果,协调者宕机了呢?
所以需要对协调者也做备份,也要做集群。这时候,问题来了,这么多协调者,听谁的呢?
精彩案例: https://blog.csdn.net/shinylp/article/details/93210128
https://www.cnblogs.com/stateis0/p/9062130.html
算法详解
角色与提案
1、提案
提案 (Proposal):Proposal
信息包括提案编号 (Proposal ID
) 和提议的值 (Value
) 。 最终要达成一致的value就在提案里。
2、角色
-
Client 客户端
客户端向分布式系统发出请求,并等待响应。例如,对分布式文件服务器中文件的写请求 。
-
Proposer提案发起者
Proposer
可以 提出提案 (Proposal
)。 -
Acceptor决策者
Acceptor
可以 接受提案。一旦接受提案,提案 里面的value
值就被选定了。 -
Learner 最终学习者
Acceptor
告诉Learner
哪个提案被选定了,那么Learner
就学习这个被选择的value
。
推导过程
1.一致性算法的前提条件
- 在被提出的
P
中,只有一个V
被选中。 - 如果没有
P
被提出,就没有V
被选中。 - 在
P
被选定后,进程都可以学习被选中的P
。
只有一个Acceptor
一个 Acceptor
接受一个 P
,那么只有一个 V
被选定。
但是当只有一个Acceptor时,存在单点问题。
多个Acceptor
约束1:
P1:一个Acceptor必须接受它收到的第一个提案。
如果每个 Proposer 会产生不同的 P,那么多个 Proposer 必定产生多个 P,发给多个 Acceptor。根据 约定 P1
,Acceptor
分别接受到 P
,就会导致不同的 V
被选定,如下图所示:
如上图所示,P1
会产生的问题: v1
、v2
、v3
都没有被选定,因为他们只有被一个 Acceptor
接受。
约定2:
P1a : 一个提案 P 被选定,需要被半数以上 Acceptor 接受.
对于 P1a
,其实就意味着 一个Acceptor必须接受不止一个提案。
显然,这与 P1
相矛盾,所以需要重新设计提案。原来的设计是: [提案P = value]
,现在重新设计 [提案P = 提案编号 + value]
,可表示为 [M,V]
。
如何保证选举的Value值相同?
约定3:
P2 : 如果提案 P[M0,V0] 被选定了,那么所有比 M0 编号更高的,且被选定的 P,其 value 的值也是 V0。
对于 P2
中的 “被选定”:一个提案要被选定,首先至少要被一个 Acceptor
批准。因此,可以理解 P2
为:
P2a : 如果提案 P[M0,V0] 被选定了,那么所有比 M0 编号更高的,且 [被Acceptor批准] 的P,其 value 值也是 V0。
只要满足 P2a
,就能满足 P2
。多提案被选择 的问题解决了,但是由于 网络不稳定 或者 宕机 的原因(不可避免),会产生新问题:
假设有 5
个 Acceptor
。Proposer2
提出 [M1,V1]
的提案,Acceptor2~5
(半数以上)均接受了该提案,于是对于 Acceptor2~5
和 Proposer2
来讲,它们都认为 V1
被选定。Acceptor1
刚刚从 宕机状态 恢复过来(之前 Acceptor1
没有收到过任何提案),此时 Proposer1
向 Acceptor1
发送了 [M2,V2]
的提案 (V2≠V1且M2>M1)。对于 Acceptor1
来讲,这是它收到的 第一个提案。根据 P1
(一个 Acceptor
必须接受它收到的 第一个提案),Acceptor1
必须接受该提案。同时 Acceptor1
认为 V2
被选定。
这就出现了两个问题:
Acceptor1
认为V2
被选定,Acceptor2~5
和Proposer2
认为V1
被选定。出现了不一致。V1
被选定了,但是 编号更高 的被Acceptor1
接受的提案[M2,V2]
的value
为V2
,且 V2≠V1。这就跟P2a
(如果某个value
为v
的提案被选定了,那么每个 编号更高 的被Acceptor
接受的提案的value
必须也是v
)矛盾了。
基于以上问题,所有就有了 P2b
:
P2b : 如果 P[M0,V0] 被选定后,任何 Proposer 产生的 P,其值也是 V0。
对于 P2b
中的描述,怎样保证 任何Proposer产生的P,其值也是V0 ?只要满足 P2c
即可:
P2c: 对于任意的 M、V,如果 [M,V] 被提出,那么存在一个半数以上的 Acceptor 组成的组合 S,满足以下两个条件中的任何一个: ① S 中没有一个接受过编号小于 M 的提案。 ② S 中的 Acceptor 接受过的最大编号的提案的 value 为 V。
Proposer生成提案
Proposer生成提案之前,应该先去『学习』已经被选定或者可能被选定的value,然后 以该value作为自己提出的提案的value。如果没有value被选定,Proposer才可以自己决定value的值。这样才能达 成一致。这个学习的阶段是通过一个『Prepare请求』实现的。 于是我们得到了如下的提案生成算法:
- Proposer选择一个新的提案编号N,然后向某个Acceptor集合(半数以上)发送请求,要求该集合中的每个 Acceptor做出如下响应(response) (a) Acceptor向Proposer承诺保证不再接受任何编号小于N的提案。 (b) 如果Acceptor已经接受过提案,那么就向Proposer反馈已经接受过的编号小于N的,但为最大编号的提案 的值。 我们将该请求称为编号为N的Prepare请求。
-
- 如果Proposer收到了半数以上的Acceptor的响应,那么它就可以生成编号为N,Value为V的提案[N,V]。这里 的V是所有的响应中编号最大的提案的Value。如果所有的响应中都没有提案,那 么此时V就可以由Proposer 自己选择。 生成提案后,Proposer将该提案发送给半数以上的Acceptor集合,并期望这些Acceptor能接受该提案。我们 称该请求为Accept请求。
Acceptor接受提案
刚刚讲解了Paxos算法中Proposer的处理逻辑,怎么去生成的提案,下面来看看Acceptor是如何批准提案的 根据刚刚的介绍,一个Acceptor可能会受到来自Proposer的两种请求,分别是Prepare请求和Accept请求,对这两 类请求作出响应的条件分别如下 Prepare请求:Acceptor可以在任何时候响应一个Prepare请求 Accept请求:在不违背Accept现有承诺的前提下,可以任意响应Accept请求 因此,对Acceptor接受提案给出如下约束:
P1a:一个Acceptor只要尚未响应过任何编号大于N的Prepare请求,那么他就可以接受这个编号为N的提案。
分布式理论:一致性算法Raft
概念
Raft是一种为了管理日志的一致性算法。
Raft算法分为3个模块:
1、领导人选举;
2、日志复制;
3、安全性。
Raft算法分为两个阶段,第一阶段是领导人的选举,第二阶段是领导人带领进行正常操作,比如日志复制。
领导人leader的选举
Raft通过选举领导人,然后给予领导人管理复制日志的责任来实现一致性。
在Raft中任何时候,一个服务器都有可能扮演下面的角色之一:
- 领导者(leader): 处理客户端交互,日志复制等动作,一般一次只有一个领导者
- 候选者( candidate ): 候选者就是在选举过程中提名自己的实体,一旦选举成功,则成为领导者
- 跟随者(follower): 类似选民,完全被动的角色,这样的服务器等待被通知投票
Raft采用心跳机制来实现选举,当server启动的时候,每一台机器都是follower,每一个server都有一个定时器,超时时间为 为election timeout(一般为150-300ms) ,如果某一个server没有超时的情况下收到来自领导者或者候选者发来的消息,则定时器重启,如果超时,则开始一次选举。
选举过程如下:
初始状态下,所有节点都是follower:
某一时刻,其中一个follower由于没有接收到leader的心跳包,率先发生超时 election timeout ,进而发起选举:
只要集群中超过半数的节点接受投票,candidate 节点将成为即切换 leader 状态。
成为 leader 节点之后,leader 将定时向 follower 节点同步日志并发送 heartbeat。
节点异常
集群中各个节点的状态随时都有可能发生变化。从实际的变化上来分类的话,节点的异常大致可以分为四种类型:
- leader 不可用;
- follower 不可用;
- 多个 candidate 或多个 leader;
- 新节点加入集群。
leader 不可用
由于某些异常导致 leader 不再发送 heartbeat ,或 follower 无法收到 heartbeat 。
当某一 follower 发生 election timeout 时,其状态变更为 candidate,并向其他 follower 发起投票。
当超过半数的 follower 接受投票后,这一节点将成为新的 leader,leader 的步进数加 1 并开始向 follower 同 步日志。
当一段时间之后,如果之前的 leader 再次加入集群,则两个 leader 比较彼此的步进数,步进数低的 leader 将 切换自己的状态为 follower。
较早前 leader 中不一致的日志将被清除,并与现有 leader 中的日志保持一致。
多个 candidate 或多个 leader
在集群中出现多个 candidate 或多个 leader 通常是由于数据传输不畅造成的。出现多个 leader 的情况相对少见, 但多个 candidate 比较容易出现在集群节点启动初期尚未选出 leader 的“混沌”时期。
初始状态下集群中的所有节点都处于 follower 状态。
两个节点同时成为 candidate 发起选举 :
两个 candidate 都只得到了少部分 follower 的接受投票:
candidate 继续向其他的 follower 询问:
由于一些 follower 已经投过票了,所以均返回拒绝接受:
candidate 也可能向一个 candidate 询问投票:
在步进数相同的情况下,candidate 将拒绝接受另一个 candidate 的请求:
由于第一次未选出 leader,candidate 将随机选择一个等待间隔(150ms ~ 300ms)再次发起投票。
日志复制(保证数据一致性)
Leader选出后,就开始接收客户端的请求。Leader把请求作为日志条目(Log entries)加入到它的日志中, 然后并行的向其他服务器发起 AppendEntries RPC复制日志条目。当这条日志被复制到大多数服务器上,Leader 将这条日志应用到它的状态机并向客户端返回执行结果。 下图表示了当一个客户端发送一个请求给领导者,随后领导者复制给跟随者的整个过程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RxdweSjG-1597151745232)(C:\文档\学习总结\总结\图片\分布式定理\31.png)]
- 客户端的每一个请求都包含被复制状态机执行的指令。
- leader把这个指令作为一条新的日志条目添加到日志中,然后并行发起 RPC 给其他的服务器,让他们复制这 条信息。
- 跟随者响应ACK,如果 follower 宕机或者运行缓慢或者丢包,leader会不断的重试,直到所有的 follower 最终 都复制了所有的日志条目。
- 通知所有的Follower提交日志,同时领导人提交这条日志到自己的状态机中,并返回给客户端。
51745232)]
由于第一次未选出 leader,candidate 将随机选择一个等待间隔(150ms ~ 300ms)再次发起投票。
日志复制(保证数据一致性)
Leader选出后,就开始接收客户端的请求。Leader把请求作为日志条目(Log entries)加入到它的日志中, 然后并行的向其他服务器发起 AppendEntries RPC复制日志条目。当这条日志被复制到大多数服务器上,Leader 将这条日志应用到它的状态机并向客户端返回执行结果。 下图表示了当一个客户端发送一个请求给领导者,随后领导者复制给跟随者的整个过程。
[外链图片转存中…(img-RxdweSjG-1597151745232)]
- 客户端的每一个请求都包含被复制状态机执行的指令。
- leader把这个指令作为一条新的日志条目添加到日志中,然后并行发起 RPC 给其他的服务器,让他们复制这 条信息。
- 跟随者响应ACK,如果 follower 宕机或者运行缓慢或者丢包,leader会不断的重试,直到所有的 follower 最终 都复制了所有的日志条目。
- 通知所有的Follower提交日志,同时领导人提交这条日志到自己的状态机中,并返回给客户端。