您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

分布式系统如何保证一致性

时间:2019-08-07 09:22:56  来源:  作者:

分布式一致性算法概要

随着各种高并发访问、海量数据处理等应用场景越来越多,为了应对这些使用场景,分布式系统应运而生。分布式系统得以发展,得益于诸多优点,比如:可以避免 单点故障 ,容易 横向扩展 等。所谓单点故障指的是:单个组件发生故障会导致整个系统的瘫痪,而容易横向扩展的意思是我们可以通过增加机器来提高整个系统的性能。分布式系统在带来诸多优点的同时,也带来了一些挑战,我们下面来重点描述清楚其中的一个核心挑战: 在分布式系统中如何保证数据的一致性 。关于分布式系统的基本概念,可以参考相关的理论书籍。

在众多分布式一致性协议中, paxos 算法经过了严格的数学证明。然而由于该算法非常难以理解,尤其是在各种系统的实现时,一般采用 paxos 的简化版本或者 paxos 的一些变种协议,比如 Raft 和 Zab 等。为此,本文选取 Raft 算法来进行介绍。我们可以通过构造一个如下的应用场景来帮助我们理解一个算法。

架构师干货总结:分布式系统如何保证一致性

 

以一个数据存储系统为例,如果 client 想要在 server 上设置一个值,假如一开始有一个 server 和 一个 client,此时只要一个server 完成值的设置即可。可是如果有多个 server 存在的话,要如何保证所有的 server 节点上存储的值是一致的呢?如果各节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。

Raft 算法介绍

在一个由 Raft 协议组织的集群中有三类角色:

  • Leader(领袖)
  • Follower(群众)
  • Candidate(候选人)

每个节点都会处于以上三种角色中的一种。

算法的主体大致可分为2个过程:

  • 选举(Leader Election)
  • 日志同步(Log Replication)

下面我们分别介绍 Raft 算法中的选举流程和日志同步流程,随后会介绍 Raft 算法对一些异常情况的处理。

选举

选举和现实社会中的民主选举制度很像,刚开始没有 Leader,所有集群中的参与者都是 Follower, 当 Follower 超过选举超时时间 ( election timeout ) 没收到来自 Leader 的心跳报文,则成为 Candidate,增加任期 ( Term ) 并向其他节点发起新的选举请求。接收到请求的节点如果还没投票,则投票给该节点,并重置自己的超时时间。如果某个 Candidate 节点接收到的选票的个数占大多数(超过 1/2), 它就会成为 Leader 节点,这就是所谓的 Leader election 的过程。每隔一定时间向 Follower 发送心跳报文来维持自己的 『统治』地位。

集群中的每个节点都处于以上三种角色中的一种,其状态转换图可以总结如下:

 

架构师干货总结:分布式系统如何保证一致性

 

 

下面通过几个例子来帮助我们理解这个选举过程:

1. 可以正常选举出 Leader 的例子 :

 

架构师干货总结:分布式系统如何保证一致性

 

 

在此例子中,一共有三个节点,复现流程如下:

  • 节点 B 首先出现心跳超时,然后变成 Candidate 角色。
  • 节点 B 首先把自己宝贵的一票投给自己,然后请求其他节点也将赞同票投给自己。
  • 节点 A 和 C 此时还未出现超时,仍然处于 Follower 角色,接收到请求后,投票给了 节点 B。
  • 节点 B 接收到的赞同票超过半数,成为 Leader 节点。

2. 平分选票的情况

由于 Raft 协议并不要求集群中的节点个数为奇数,于是在四个节点的集群中,可能出现如下的情况:

 

架构师干货总结:分布式系统如何保证一致性

 

 

复现流程如下:

  • 节点 B 和 C 几乎同时心跳超时,成为 Candidate 角色。
  • 节点 B 和 C 均将自己的赞同票投给自己。
  • 节点 A 投给了节点 B,而 节点 D 则投给了节点 C。
  • 出现两个 Candidate 的选票相同的情况。

当出现这种情况的时候,没有任何一个节点接收到的赞同票超过半数,于是此选举过程不会有 Leader 角色出现。大家各自等待超时,然后开启下一轮的选举流程。

疑问:那有没有可能在下一轮的选举过程依然出现平分选票的情况?答案是有的,可是 Raft 有一个机制可以避免此种情况持续发生: 每个节点的超时时间都是随机的 ,这样就可以尽量避免多次出现以上的情况。

架构师干货总结:分布式系统如何保证一致性

 

3. 选举流程要点总结

「1」Leader 角色通过发送心跳报文来维护自己的统治地位。「2」Follower 角色接收不到心跳报文,则超时开始下一轮的选举。「3」每个节点的超时时间都是随机的。「4」成为 Leader 节点需要赞同票超过半数。「5」选举结束,所有除 Leader 的候选人又变回 Follower 服从 Leader。

日志同步

当选举完成后,客户端进行的操作都要通过 Leader 来进行。Leader 接受到客户端发来的操作请求后,首先记录到日志中,此时为 uncommitted 状态。然后在下一个心跳报文中通知所有 Follower,当大多数 Follower 响应 ACK 后,Leader 响应客户端,进入 committed 阶段,并向 Follower 发送 commit 通知应用( Apply )操作。

日志同步流程如下:

 

架构师干货总结:分布式系统如何保证一致性

 

 

上图中的序号对应一个存储的步骤, 日志同步 流程总结如下:「1」client 给 Leader 发送一个操作请求,假设为 SET X=8。「2」Leader 会把 SET X=8 这个操作记录到本地 log,此时为 uncommited 状态,同时将这个操作发送给所有的 Follower。「3」Follower 接收到操作请求后,也将 SET X=8 这个操作记录到本地 log(uncommited 状态),然后给 Leader 回复 ACK 信息。「4」Leader 节点当接收到的 ACK 超过半数后,给 client 回复 ACK 信息,进入 commited 阶段。「5」Leader 节点首先应用自己的 log,然后将 commit 消息发送给 Follower, 让 Follower 也 应用自己存储的日志信息。

架构师干货总结:分布式系统如何保证一致性

 

Raft 中的异常处理

我们已经介绍了 Raft 算法的正常处理流程,然而现实总是很骨感,会出现各种异常的情况。client 和 Leader 之间的通信异常,不会影响到集群内部状态的一致性,不再赘述;如果在一个任期内,Follower 角色宕机,处理流程比较简单。其呈现出来的现象就是 步骤「3」异常,然而只要 Leader 能够接收到超过半数的 ACK,就不会影响到正常的存储流程。但是 Leader 角色会针对该 Follower 节点,持续进行步骤 「2」 的动作,直到接收到步骤 「3」的回应信息或者我们把该 Follower 节点从集群中拿掉;Raft 协议强依赖 Leader 节点的可用性来确保集群数据的一致性。下面重点介绍在各种情况下 Leader 节点出现故障时,Raft 协议是如何保障数据一致性的。

1. 写操作 到达 Leader 节点,但尚未同步到 Follower 节点

此刻集群的状态如下,用方框中的灰色表示当前处于 uncommited 状态。

 

架构师干货总结:分布式系统如何保证一致性

 

 

如果集群在此状态,Leader 节点宕机,则 Raft 的处理流程如下:「1」Follower 节点超时,然后选举出新一任期的 Leader,然后它并没有处于 uncommited 状态的日志。「2」Client 节点由于 Ack 超时,可安全发起重试。「3」原来的 Leader 节点恢复后以 Follower 角色重新加入集群。并从当前任期的新 Leader 处同步数据,可能会覆盖原来处于 uncommited 状态的日志。

2. 写操作 到达 Leader 节点,且将写操作同步到 Follower 节点,但还未向 Leader 回复 ACK 信息。

此刻集群的状态如下,用方框中的灰色表示当前处于 uncommited 状态。

架构师干货总结:分布式系统如何保证一致性

 

如果集群在此状态,Leader 节点宕机,则 Raft 的处理流程如下:「1」Follower 节点超时,然后选举出新一任期的 Leader,并且它存在处于 uncommited 状态的日志。「2」新的 Leader 节点假装没有刚才的选举过程,继续从步骤(2)开始执行,以完成数据的提交。「3」Client 节点由于 ACK 超时,可安全发起重试。「4」原来的 Leader 节点恢复后以 Follower 角色重新加入集群。并从当前任期的新 Leader 处同步数据。

此时,在上面步骤「1」中选举新的 Leader 节点时,需要满足一个限制条件,即新的 Leader 节点需要具有最新的日志信息,所谓的最新是通过任期和日志的偏移量两个参数来判定的,这个限制是为了解决只有部分 Follower 节点接收到写操作请求的情况。

3. Leader 节点接收到写操作的 ACK 信息,处于 commited 状态,然而 Follower 处于 uncommited 状态。

此种情况是由于,在步骤(5)执行过程中,Leader 宕机导致的,此刻集群的状态如下,用方框中的灰色表示当前处于 uncommited 状态,用方框中的黑色表示当前处于 commited 状态,同时圆圈中的值表示操作已经生效。

 

架构师干货总结:分布式系统如何保证一致性

 

 

对于此种情况,Raft 协议的处理流程和上面情况2的处理流程是一样的。

4. 脑裂

由于网络故障,产生分区将原先的 Leader 节点和 Follower 节点分隔开,Follower 收不到 Leader 的心跳将发起选举,产生新的 Leader,这时就产生了双 Leader,这就是所谓的脑裂。这种情况下某些 Leader 由于获取不到大多数的投票,所以数据永远不会提交成功。当网络故障恢复后,旧的 Leader 发现有 Term 更新的 Leader 存在,则自动降级为 Follower 并从最新的 Leader 同步数据达成集群一致。

总结

本文以 Raft 协议为契机来介绍分布式环境中的一致性。首先介绍了 Leader 选举和日志同步的过程,然后介绍了 Raft 协议是如何处理各种异常情况的。通过 Raft 协议的学习,不仅可以对分布式一致性有一个概括性的了解,同时也会有助于对其他一致性协议(比如 paxox)的学习。在此基础上,可以尝试阅读一些 Raft 开源的实现, 以加深进一步的理解。



Tags:分布式系统   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
随着移动互联网技术的快速发展,在新业务、新领域、新场景的驱动下,基于传统大型机的服务部署方式,不仅难以适应快速增长的业务需求,而且持续耗费高昂的成本,从而使得各大生产厂商...【详细内容】
2021-12-08  Tags: 分布式系统  点击:(23)  评论:(0)  加入收藏
分布式一致性算法概要随着各种高并发访问、海量数据处理等应用场景越来越多,为了应对这些使用场景,分布式系统应运而生。分布式系统得以发展,得益于诸多优点,比如:可以避免 单点...【详细内容】
2021-04-13  Tags: 分布式系统  点击:(238)  评论:(0)  加入收藏
分布式系统的经典理论分布式系统从诞生到现在已经有几十个年头了,其中伴随着一些很重要的基础理论,正是这些影响深远的基础理论,奠定了分布式系统的坚实基础,造就了分布式领域的...【详细内容】
2021-04-13  Tags: 分布式系统  点击:(263)  评论:(0)  加入收藏
分布式理论知识1、分布式系统架构1.1基础概念分布式 : 将一个单体项目分成很多个模块,各个模块协同工作,各个模块构成了分布式系统集群:针对单个模块或者单个系统在多台服务器上...【详细内容】
2021-01-28  Tags: 分布式系统  点击:(111)  评论:(0)  加入收藏
一致性问题一致性问题是分布式领域最重要、最基础的问题。一致性/Consistency,是说在有多个服务节点的情况下,执行一些列操作,在约定协议的保障下,使得他们对外的处理结果,能达...【详细内容】
2020-12-15  Tags: 分布式系统  点击:(149)  评论:(0)  加入收藏
在分布式系统,尤其是微服务系统中,一次外部请求往往需要内部多个模块,多个中间件,多台机器的相互调用才能完成。在这一系列的调用中,可能有些是串行的,而有些是并行的。在这种情况...【详细内容】
2020-12-11  Tags: 分布式系统  点击:(158)  评论:(0)  加入收藏
现如今可谓是微服务、分布式、IoT(物联网)横行的时代,作为一名开发者始终还是要保持一定的危机意识,特别是在日常的项目开发中,若是有机会接触到一些关于微服务、分布式下的应用...【详细内容】
2020-12-01  Tags: 分布式系统  点击:(114)  评论:(0)  加入收藏
分布式系统如何寻址?通过 RPC 框架,能够解决服务之间的跨网络通信问题,是微服务改造的基础。服务拆分之后,需要维护更多细粒度的服务,这样就涉及到 RPC 客户端服到服务端的 部署...【详细内容】
2020-11-04  Tags: 分布式系统  点击:(103)  评论:(0)  加入收藏
上一篇《CAP》写完之后,我又反复回看了多次,发现最后的一部分表达CAP、ACID、BASE、“BACP(自造)”关系时有一些问题,并且不是很严谨,但是无奈已经发送过的内容,无法支持修改,并且有挺多小伙伴都在私聊我确认细节,这里我来重...【详细内容】
2020-09-16  Tags: 分布式系统  点击:(46)  评论:(0)  加入收藏
介绍OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。OAuth...【详细内容】
2020-08-18  Tags: 分布式系统  点击:(65)  评论:(0)  加入收藏
▌简易百科推荐
为了构建高并发、高可用的系统架构,压测、容量预估必不可少,在发现系统瓶颈后,需要有针对性地扩容、优化。结合楼主的经验和知识,本文做一个简单的总结,欢迎探讨。1、QPS保障目标...【详细内容】
2021-12-27  大数据架构师    Tags:架构   点击:(5)  评论:(0)  加入收藏
前言 单片机开发中,我们往往首先接触裸机系统,然后到RTOS,那么它们的软件架构是什么?这是我们开发人员必须认真考虑的问题。在实际项目中,首先选择软件架构是非常重要的,接下来我...【详细内容】
2021-12-23  正点原子原子哥    Tags:架构   点击:(7)  评论:(0)  加入收藏
现有数据架构难以支撑现代化应用的实现。 随着云计算产业的快速崛起,带动着各行各业开始自己的基于云的业务创新和信息架构现代化,云计算的可靠性、灵活性、按需计费的高性价...【详细内容】
2021-12-22    CSDN  Tags:数据架构   点击:(10)  评论:(0)  加入收藏
▶ 企业级项目结构封装释义 如果你刚毕业,作为Java新手程序员进入一家企业,拿到代码之后,你有什么感觉呢?如果你没有听过多模块、分布式这类的概念,那么多半会傻眼。为什么一个项...【详细内容】
2021-12-20  蜗牛学苑    Tags:微服务   点击:(9)  评论:(0)  加入收藏
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  青锋爱编程    Tags:后台架构   点击:(21)  评论:(0)  加入收藏
在了解连接池之前,我们需要对长、短链接建立初步认识。我们都知道,网络通信大部分都是基于TCP/IP协议,数据传输之前,双方通过“三次握手”建立连接,当数据传输完成之后,又通过“四次挥手”释放连接,以下是“三次握手”与“四...【详细内容】
2021-12-14  架构即人生    Tags:连接池   点击:(17)  评论:(0)  加入收藏
随着移动互联网技术的快速发展,在新业务、新领域、新场景的驱动下,基于传统大型机的服务部署方式,不仅难以适应快速增长的业务需求,而且持续耗费高昂的成本,从而使得各大生产厂商...【详细内容】
2021-12-08  架构驿站    Tags:分布式系统   点击:(23)  评论:(0)  加入收藏
本系列为 Netty 学习笔记,本篇介绍总结Java NIO 网络编程。Netty 作为一个异步的、事件驱动的网络应用程序框架,也是基于NIO的客户、服务器端的编程框架。其对 Java NIO 底层...【详细内容】
2021-12-07  大数据架构师    Tags:Netty   点击:(17)  评论:(0)  加入收藏
前面谈过很多关于数字化转型,云原生,微服务方面的文章。虽然自己一直做大集团的SOA集成平台咨询规划和建设项目,但是当前传统企业数字化转型,国产化和自主可控,云原生,微服务是不...【详细内容】
2021-12-06  人月聊IT    Tags:架构   点击:(23)  评论:(0)  加入收藏
微服务看似是完美的解决方案。从理论上来说,微服务提高了开发速度,而且还可以单独扩展应用的某个部分。但实际上,微服务带有一定的隐形成本。我认为,没有亲自动手构建微服务的经历,就无法真正了解其复杂性。...【详细内容】
2021-11-26  GreekDataGuy  CSDN  Tags:单体应用   点击:(35)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条