分布式-分布式理论笔记

文章详细介绍了分布式系统中的一致性问题,包括CAP理论中的可扩展性、无状态、不出现单点故障等特点,以及在分区容忍性下如何选择一致性和可用性。接着,阐述了BASE理论,即基本可用、软状态和最终一致性,以及在实际系统设计中的应用。文章还深入探讨了Paxos算法,解释了其节点角色、交互过程和崩溃恢复机制。最后,以Zookeeper为例,说明了Zab协议如何在实际应用中保证数据一致性。
摘要由CSDN通过智能技术生成

分布式系统的特点

分布式系统技术就是用来解决集中式架构的性能瓶颈问题,来适应快速发展的业务规模,是建立在网络之上的硬件或者软件系统,彼此之间通过消息等方式进行通信和协调。

特点

具有可扩展性,不出现单点故障、服务或者存储无状态等特点。

单点故障(Single Point Failure):在系统中某个组件一旦失效,这会让整个系统无法工作。
无状态:是因为无状态的服务才能满足部分机器宕机不影响全部,可以随时进行扩展的需求。

CAP理论和BASE理论

CAP理论

CAP 理论

一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容忍性(Partition Tolerance)这三项中的两项。img

一致性:是指“所有节点同时看到相同的数据”,所有节点拥有数据的最新版本。
可用性:是指“任何时候,读写都是成功的”,即服务一直可用,而且是正常响应时间。
SLA,即服务水平协议。比如我们说月度 99.95% 的 SLA,则意味着每个月服务出现故障的时间只能占总时间的 0.05%,如果这个月是 30 天,那么就是 21.6 分钟。
分区容忍性:是指“当部分节点出现消息丢失或者分区故障的时候,分布式系统仍然能够继续运行”,即系统容忍网络出现分区,并且在遇到某节点或网络分区之间网络不可达的情况下,仍然能够对外提供满足一致性和可用性的服务。
分布式系统中,由于系统的各层拆分,P 是确定的,CAP 的应用模型就是 CP 架构和 AP 架构。分布式系统所关注的,就是在 Partition Tolerance 的前提下,如何实现更好的 A 和更稳定的 C。

CAP 理论的证明

反证法来证明 CAP 定理:通过一个实际场景,如果 CAP 三者可同时满足,由于允许 P 的存在,则一定存在 Server 之间的丢包,如此则不能保证 C。首先构造一个单机系统,如上图,Client A 可以发送指令到 Server 并且设置更新 X 的值,Client 1 从 Server 读取该值,在单点情况下,即没有网络分区的情况下,通过简单的事务机制,可以保证 Client 1 读到的始终是最新值,不存在一致性的问题。
在这里插入图片描述

在系统中增加一组节点,因为允许分区容错,Write 操作可能在 Server 1 上成功,在 Server 2 上失败,这时候对于 Client 1 和 Client 2,就会读取到不一致的值,出现不一致的情况。如果要保持 X 值的一致性,Write 操作必须同时失败, 也就是降低系统的可用性。 可以看到,在分布式系统中,无法同时满足 CAP 定律中的“一致性”“可用性”和“分区容错性”三者。
在这里插入图片描述

在该证明中,对 CAP 的定义进行了更明确的声明:

  • Consistency,一致性被称为原子对象,任何的读写都应该看起来是“原子”的,或串行的,写后面的读一定能读到前面写的内容,所有的读写请求都好像被全局排序;
  • Availability,对任何非失败节点都应该在有限时间内给出请求的回应(请求的可终止性);
  • Partition Tolerance,允许节点之间丢失任意多的消息,当网络分区发生时,节点之间的消息可能会完全丢失。
CAP 理论的应用

在架构设计中,要合理进行取舍,CAP 理论类似数学上的不可能三角,只能三者选其二,不能全部获得。
不同业务对于一致性的要求是不同的。在微博上发表评论和点赞,用户对不一致是不敏感的,可以容忍相对较长时间的不一致,只要做好本地的交互,并不会影响用户体验;而我们在电商购物时,产品价格数据则是要求强一致性的,如果商家更改价格不能实时生效,则会对交易成功率有非常大的影响。
注意CAP 理论中是忽略网络延迟的,也就是当事务提交时,节点间的数据复制一定是需要花费时间的。即使是同一个机房,从节点 A 复制到节点 B,由于现实中网络不是实时的,所以总会有一定的时间不一致。

CP 和 AP 架构的取舍
在通常的分布式系统中,为了保证数据的高可用,通常会将数据保留多个副本(Replica),网络分区是既成的现实,如何在保持相对一致性的前提下,提高系统的可用性。 业务上对一致性的要求会直接反映在系统设计中,典型的就是 CP 和 AP 结构。
CP 架构:对于 CP 来说,放弃可用性,追求一致性和分区容错性。
ZooKeeper,就是采用了 CP 一致性,ZooKeeper 是一个分布式的服务框架,主要用来解决分布式集群中应用系统的协调和一致性问题。其核心算法是 Zab,所有设计都是为了一致性。在 CAP 模型中,ZooKeeper 是 CP,这意味着面对网络分区时,为了保持一致性,它是不可用的。

AP 架构:对于 AP 来说,放弃强一致性,追求分区容错性和可用性,这是很多分布式系统设计时的选择,后面的 Base 也是根据 AP 来扩展的。
Eureka 是 Spring Cloud 微服务技术栈中的服务发现组件,Eureka 的各个节点都是平等的,几个节点挂掉不影响正常节点的工作,剩余的节点依然可以提供注册和查询服务,只要有一台 Eureka 还在,就能保证注册服务可用,只不过查到的信息可能不是最新的版本,不保证一致性。

Base 理论

Base :基本可用(Basically Available)、软状态(Soft State)和最终一致性(Eventually Consistent)。
核心思想是最终一致性,即使无法做到强一致性(Strong Consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual Consistency)。

基本可用

基本可用就是不追求 CAP 中的「任何时候,读写都是成功的」,而是系统能够基本运行,一直提供服务。强调了分布式系统在出现不可预知故障的时候,允许损失部分可用性,相比正常的系统,可能是响应时间延长,或者是服务被降级。 举个例子,在双十一秒杀活动中,如果抢购人数太多超过了系统的 QPS 峰值,可能会排队或者提示限流,这就是通过合理的手段保护系统的稳定性,保证主要的服务正常,保证基本可用。

软状态

软状态允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。

最终一致性

数据不可能一直是软状态,必须在一个时间期限之后达到各个节点的一致性,在期限过后,应当保证所有副本保持数据一致性,也就是达到数据的最终一致性。 在系统设计中,最终一致性实现的时间取决于网络延时、系统负载、不同的存储选型、不同数据复制方案设计等因素。

全局时钟和逻辑时钟

全局时钟

分布式系统解决了传统单体架构的单点问题和性能容量问题,也带来多节点的时间同步问题:不同机器上的物理时钟难以同步,导致无法区分在分布式系统中多个节点的事件时序。 没有全局时钟,绝对的内部一致性是没有意义的, 一致性都是外部一致性,而外部一致性主要指的是多并发访问时更新过的数据如何获取的问题。

逻辑时钟

逻辑时钟描绘了分布式系统中事件发生的时序,是为了区分现实中的物理时钟提出来的概念。一般情况下我们提到的时间都是指物理时间,但实际上很多应用中,只要所有机器有相同的时间就够了,这个时间不一定要跟实际时间相同。
即:如果两个节点之间不进行交互,那么它们的时间甚至都不需要同步。 因此问题的关键点在于节点间的交互要在事件的发生顺序上达成一致,而不是对于时间达成一致。 逻辑时钟的概念也被用来解决分布式一致性问题。

不同数据一致性模型

数据一致性模型可以分为强一致性和弱一致性,强一致性也叫做线性一致性,除此以外,所有其他的一致性都是弱一致性的特殊情况。
弱一致性根据不同的业务场景,又可以分解为更细分的模型,不同一致性模型又有不同的应用场景。 在互联网领域的绝大多数场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。
在这里插入图片描述

强一致性

当更新操作完成之后,任何多个后续进程的访问都会返回最新的更新过的值。根据 CAP 理论,这种实现需要牺牲可用性。

弱一致性

系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。这段时间为“不一致性窗口”。

最终一致性

最终一致性是弱一致性的特例,强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。 到达最终一致性的时间 ,就是不一致窗口时间,在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响。 最终一致性模型根据其提供的不同保证可以划分为更多的模型,包括因果一致性和会话一致性等。

因果一致性

因果一致性要求有因果关系的操作顺序得到保证,非因果关系的操作顺序则无所谓。
进程 A 在更新完某个数据项后通知了进程 B,那么进程 B 之后对该数据项的访问都应该能够获取到进程 A 更新后的最新值,并且如果进程 B 要对该数据项进行更新操作的话,务必基于进程 A 更新后的最新值。
因果一致性的应用场景,在微博或者微信进行评论的时候,比如你在朋友圈发了一张照片,朋友给你评论了,而你对朋友的评论进行了回复,这条朋友圈的显示中,你的回复必须在朋友之后,这是一个因果关系,而其他没有因果关系的数据,可以允许不一致。

会话一致性

会话一致性将对系统数据的访问过程框定在了一个会话当中,约定了系统能保证在同一个有效的会话中实现“读己之所写”的一致性,就是在你的一次访问中,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。 实际开发中有分布式的 Session 一致性问题,可以认为是会话一致性的一个应用。

CAP 及 Base 的关系

CAP 理论描述了分布式系统中数据一致性、可用性、分区容错性之间的制约关系,当你选择了其中的两个时,就不得不对剩下的一个做一定程度的牺牲。
Base 理论是对 CAP 理论的实际应用,在分区和副本存在的前提下,通过一定的系统设计方案,放弃强一致性,实现基本可用,这是大部分分布式系统的选择,比如 NoSQL 系统、微服务架构。

理解 Paxos 算法

Quorum 机制

在 N 个副本中,一次更新成功的如果有 W 个,在读取数据时是要从大于 N-W 个副本中读取,这样就能至少读到一个更新的数据了。
和 Quorum 机制对应的是 WARO,也就是Write All Read one,是一种简单的副本控制协议,当 Client 请求向某副本写数据时(更新数据),只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。 WARO 优先保证读服务,因为所有的副本更新成功,才能视为更新成功,从而保证了所有的副本一致,这样的话,只需要读任何一个副本上的数据即可。写服务的可用性较低,因为只要有一个副本更新失败,此次写操作就视为失败了。假设有 N 个副本,N-1 个都宕机了,剩下的那个副本仍能提供读服务;但是只要有一个副本宕机了,写服务就不会成功。
WARO 牺牲了更新服务的可用性,最大程度地增强了读服务的可用性,而 Quorum 就是在更新服务和读服务之间进行的一个折衷。

Quorum 定义

Quorum 的定义如下:假设有 N 个副本,更新操作 wi 在 W 个副本中更新成功之后,才认为此次更新操作 wi 成功,把这次成功提交的更新操作对应的数据叫做:“成功提交的数据”。对于读操作而言,至少需要读 R 个副本才能读到此次更新的数据,其中,W+R>N ,即 W 和 R 有重叠,一般,W+R=N+1。
N = 存储数据副本的数量
W = 更新成功所需的副本
R = 一次数据对象读取要访问的副本的数量
Quorum就是限定了一次需要读取至少N+1-w的副本数据。
举个例子,我们维护了10个副本,一次成功更新了三个,那么至少需要读取八个副本的数据,可以保证我们读到了最新的数据。

Quorum 应用

Quorum 机制无法保证强一致性,也就是无法实现任何时刻任何用户或节点都可以读到最近一次成功提交的副本数据。 Quorum 机制的使用需要配合一个获取最新成功提交的版本号的 metadata 服务,这样可以确定最新已经成功提交的版本号,然后从已经读到的数据中就可以确认最新写入的数据。 Quorum 是分布式系统中常用的一种机制,用来保证数据冗余和最终一致性的投票算法,在 Paxos、Raft 和 ZooKeeper 的 Zab 等算法中,都可以看到 Quorum 机制的应用。

Paxos 节点的角色和交互

Paxos 的节点角色

Paxos 协议中,有三类节点角色,分别是 Proposer提案者、Acceptor批准者 和 Learner学习者,另外还有一个 Client,作为产生议题者。
Proposer 提案者
Proposer 可以有多个,在流程开始时,Proposer 提出议案,也就是value,所谓 value,在工程中可以是任何操作,比如“修改某个变量的值为某个新值”,Paxos 协议中统一将这些操作抽象为 value。 不同的 Proposer 可以提出不同的甚至矛盾的 value。
比如某个 Proposer 提议“将变量 X 设置为 1”,另一个 Proposer 提议“将变量 X 设置为 2”,但对同一轮 Paxos 过程,最多只有一个 value 被批准。
Acceptor 批准者
在集群中,Acceptor 有 N 个,Acceptor 之间完全对等独立,Proposer 提出的 value 必须获得超过半数(N/2+1)的 Acceptor 批准后才能通过。
Learner 学习者
Learner 不参与选举,而是学习被批准的 value,在Paxos中,Learner主要参与相关的状态机同步流程。

这里Leaner的流程就参考了Quorum 议会机制,某个 value 需要获得 W=N/2 + 1 的 Acceptor 批准,Learner 需要至少读取 N/2+1 个 Accpetor,最多读取 N 个 Acceptor 的结果后,才能学习到一个通过的 value。
Client 产生议题者
Client 角色,作为产生议题者,实际不参与选举过程,比如发起修改请求的来源等。

Proposer 与 Acceptor 之间的交互

Paxos 中, Proposer 和 Acceptor 是算法核心角色,Paxos 描述的就是在一个由多个 Proposer 和多个 Acceptor 构成的系统中,如何让多个 Acceptor 针对 Proposer 提出的多种提案达成一致的过程,而 Learner 只是“学习”最终被批准的提案。 Proposer 与 Acceptor 之间的交互主要有 4 类消息通信

  • Proposer-> Acceptor:prepare
  • Acceptor->Proposer:Promis
  • Proposer->Acceptor:accept
  • Acceptor->Proposer:accepted
Proposer 与 Acceptor 之间的交互

选举过程可以分为两个部分,准备阶段和选举阶段.
在这里插入图片描述
Phase 1 准备阶段
Proposer 生成全局唯一且递增的 ProposalID,向 Paxos 集群的所有机器发送 Prepare 请求,这里不携带 value,只携带 N 即 ProposalID。 Acceptor 收到 Prepare 请求后,判断收到的 ProposalID 是否比之前已响应的所有提案的 N 大,如果是,则:

  • 在本地持久化 N,可记为 Max_N;
  • 回复请求,并带上已经 Accept 的提案中 N 最大的 value,如果此时还没有已经 Accept 的提案,则返回 value 为空;
  • 做出承诺,不会 Accept 任何小于 Max_N 的提案。 如果否,则不回复或者回复 Error。
    Phase 2 选举阶段
    为了方便描述,我们把 Phase 2 选举阶段继续拆分为 P2a、P2b 和 P2c。
    P2a:Proposer 发送 Accept
    经过一段时间后,Proposer 收集到一些 Prepare 回复,有下列几种情况:
  • 若回复数量 > 一半的 Acceptor 数量,且所有回复的 value 都为空时,则 Porposer 发出 accept 请求,并带上自己指定的 value。
  • 若回复数量 > 一半的 Acceptor 数量,且有的回复 value 不为空时,则 Porposer 发出 accept 请求,并带上回复中 ProposalID 最大的 value,作为自己的提案内容。
  • 若回复数量 <= 一半的 Acceptor 数量时,则尝试更新生成更大的 ProposalID,再转到准备阶段执行。
    P2b:Acceptor 应答 Accept
    Accpetor 收到 Accpet 请求 后,判断:
  • 若收到的 N >= Max_N(一般情况下是等于),则回复提交成功,并持久化 N 和 value;
  • 若收到的 N < Max_N,则不回复或者回复提交失败。
    P2c: Proposer 统计投票
    经过一段时间后,Proposer 会收集到一些 Accept 回复提交成功的情况,比如:
  • 当回复数量 > 一半的 Acceptor 数量时,则表示提交 value 成功,此时可以发一个广播给所有的 Proposer、Learner,通知它们已 commit 的 value;
  • 当回复数量 <= 一半的 Acceptor 数量时,则尝试更新生成更大的 ProposalID,转到准备阶段执行。
  • 当收到一条提交失败的回复时,则尝试更新生成更大的 ProposalID,也会转到准备阶段执行。
Paxos 常见的问题

1.如果半数以内的 Acceptor 失效,如何正常运行?
在Paxos流程中,如果出现半数以内的 Acceptor 失效,可以分为两种情况:
第一种,如果半数以内的 Acceptor 失效时还没确定最终的 value,此时所有的 Proposer 会重新竞争提案,最终有一个提案会成功提交。
第二种,如果半数以内的 Acceptor 失效时已确定最终的 value,此时所有的 Proposer 提交前必须以最终的 value 提交,也就是Value实际已经生效,此值可以被获取,并不再修改。
2. Acceptor需要接受更大的N,也就是ProposalID有什么意义?
这种机制可以防止其中一个Proposer崩溃宕机产生阻塞问题,允许其他Proposer用更大ProposalID来抢占临时的访问权。
3. 如何产生唯一的编号,也就是 ProposalID?
在《Paxos made simple》论文中提到,唯一编号是让所有的 Proposer 都从不相交的数据集合中进行选择,需要保证在不同Proposer之间不重复,比如系统有 5 个 Proposer,则可为每一个 Proposer 分配一个标识 j(0~4),那么每一个 Proposer 每次提出决议的编号可以为 5*i + j,i 可以用来表示提出议案的次数。

ZooKeeper 如何保证数据一致性

Zab 一致性协议

ZooKeeper 是通过 Zab 协议来保证分布式事务的最终一致性。Zab(ZooKeeper Atomic Broadcast,ZooKeeper 原子广播协议)支持崩溃恢复,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间数据一致性。
在这里插入图片描述
在 ZooKeeper 集群中,所有客户端的请求都是写入到 Leader 进程中的,然后,由 Leader 同步到其他节点,称为 Follower。在集群数据同步的过程中,如果出现 Follower 节点崩溃或者 Leader 进程崩溃时,都会通过 Zab 协议来保证数据一致性。
Zab 协议的具体实现可以分为以下两部分:

  • 消息广播阶段:Leader 节点接受事务提交,并且将新的 Proposal 请求广播给 Follower 节点,收集各个节点的反馈,决定是否进行 Commit,在这个过程中,也会使用到的 Quorum 选举机制。
  • 崩溃恢复阶段:如果在同步过程中出现 Leader 节点宕机,会进入崩溃恢复阶段,重新进行 Leader 选举,崩溃恢复阶段还包含数据同步操作,同步集群中最新的数据,保持集群的数据一致性。
    整个 ZooKeeper 集群的一致性保证就是在上面两个状态之前切换,当 Leader 服务正常时,就是正常的消息广播模式;当 Leader 不可用时,则进入崩溃恢复模式,崩溃恢复阶段会进行数据同步,完成以后,重新进入消息广播阶段。

Zab 协议中的 Zxid

Zxid 在 ZooKeeper 的一致性流程中非常重要,Zxid 是 Zab 协议的一个事务编号,Zxid 是一个 64 位的数字,其中低 32 位是一个简单的单调递增计数器,针对客户端每一个事务请求,计数器加 1;而高 32 位则代表 Leader 周期年代的编号。
Leader 可以理解为当前集群所处的年代或者周期,对比另外一个一致性算法 Raft 中的 Term 概念。在 Raft 中,每一个任期的开始都是一次选举,Raft 算法保证在给定的一个任期最多只有一个领导人。
Zab 协议的实现也类似,每当有一个新的 Leader 选举出现时,就会从这个 Leader 服务器上取出其本地日志中最大事务的 Zxid,并从中读取 epoch 值,然后加 1,以此作为新的周期 ID。总结一下,高 32 位代表了每代 Leader 的唯一性,低 32 位则代表了每代 Leader 中事务的唯一性。

Zab 流程分析

Zab 的具体流程可以拆分为消息广播、崩溃恢复和数据同步。

消息广播

在 ZooKeeper 中所有的事务请求都由 Leader 节点来处理,其他服务器为 Follower,Leader 将客户端的事务请求转换为事务 Proposal,并且将 Proposal 分发给集群中其他所有的 Follower。
完成广播之后,Leader 等待 Follwer 反馈,当有过半数的 Follower 反馈信息后,Leader 将再次向集群内 Follower 广播 Commit 信息,Commit 信息就是确认将之前的 Proposal 提交。
Leader 节点的写入也是一个两步操作,第一步是广播事务操作,第二步是广播提交操作,其中过半数指的是反馈的节点数 >=N/2+1,N 是全部的 Follower 节点数量。

消息广播的过程描述可以参考下图:
在这里插入图片描述

  • 客户端的写请求进来之后,Leader 会将写请求包装成 Proposal 事务,并添加一个递增事务 ID,也就是 Zxid,Zxid 是单调递增的,以保证每个消息的先后顺序;
  • 广播这个 Proposal 事务,Leader 节点和 Follower 节点是解耦的,通信都会经过一个先进先出的消息队列,Leader 会为每一个 Follower 服务器分配一个单独的 FIFO 队列,然后把 Proposal 放到队列中;
  • Follower 节点收到对应的 Proposal 之后会把它持久到磁盘上,当完全写入之后,发一个 ACK 给 Leader;
  • 当 Leader 收到超过半数 Follower 机器的 ack 之后,会提交本地机器上的事务,同时开始广播 commit, Follower 收到 commit 之后,完成各自的事务提交。
崩溃恢复

消息广播通过 Quorum 机制,解决了 Follower 节点宕机的情况, Zab 协议支持崩溃恢复,崩溃恢复可以保证在 Leader 进程崩溃的时候可以重新选出 Leader,并且保证数据的完整性。
崩溃恢复和集群启动时的选举过程是一致的。

  • 初始化集群,刚刚启动的时候
  • Leader 崩溃,因为故障宕机
  • Leader 失去了半数的机器支持,与集群中超过一半的节点断连
    崩溃恢复模式将会开启新的一轮选举,选举产生的 Leader 会与过半的 Follower 进行同步,使数据一致,当与过半的机器同步完成后,就退出恢复模式, 然后进入消息广播模式。
    Zab 中的节点有三种状态,伴随着的 Zab 不同阶段的转换,节点状态也在变化:
  • following:当前节点是跟随者,服从leader节点的命令
  • leading:当前节点是Leader,负责协调事务
  • election/looking:节点处于选举状态

假设正在运行的集群有五台 Follower 服务器,编号分别是 Server1、Server2、Server3、Server4、Server5,当前 Leader 是 Server2,若某一时刻 Leader 挂了,此时便开始 Leader 选举。

选举过程如下:

1.各个节点变更状态,变更为Looking
ZooKeeper 中除了 Leader 和 Follower,还有 Observer 节点,Observer 不参与选举,Leader 挂后,余下的 Follower 节点都会将自己的状态变更为 Looking,然后开始进入 Leader 选举过程。
2.各个Server节点都会发出一个投票,参与选举
在第一次投票中,所有的 Server 都会投自己,然后各自将投票发送给集群中所有机器,在运行期间,每个服务器上的 Zxid 大概率不同。
3集群接收来自各个服务器的投票,开始处理投票和选举
处理投票的过程就是对比 Zxid 的过程,假定 Server3 的 Zxid 最大,Server1 判断 Server3 可以成为 Leader,那么 Server1 就投票给 Server3,判断的依据如下:

  • 首先选举 epoch 最大的
  • 如果 epoch 相等,则选 zxid 最大的
  • 若 epoch 和 zxid 都相等,则选择 server id 最大的,就是配置 zoo.cfg 中的 myid
    在选举过程中,如果有节点获得超过半数的投票数,则会成为 Leader 节点,反之则重新投票选举。
    在这里插入图片描述
    4选举成功,改变服务器的状态,参考上面这张图的状态变更
数据同步

崩溃恢复完成选举以后就是数据同步,在选举过程中,通过投票已经确认 Leader 服务器是最大Zxid 的节点,同步阶段就是利用 Leader 前一阶段获得的最新Proposal历史,同步集群中所有的副本。

Zab 与 Paxos 算法的联系与区别

Paxos 的思想在很多分布式组件中都可以看到,Zab 协议可以认为是基于 Paxos 算法实现的。
联系

  • 都存在一个 Leader 进程的角色,负责协调多个 Follower 进程的运行
  • 都应用 Quorum 机制,Leader 进程都会等待超过半数的 Follower 做出正确的反馈后,才会将一个提案进行提交
  • 在 Zab 协议中,Zxid 中通过 epoch 来代表当前 Leader 周期,在 Paxos 算法中,同样存在这样一个标识,叫做 Ballot Number
    区别
    Paxos 是理论,Zab 是实践,Paxos 是论文性质的,目的是设计一种通用的分布式一致性算法,而 Zab 协议应用在 ZooKeeper 中,是一个特别设计的崩溃可恢复的原子消息广播算法。

Zab 协议增加了崩溃恢复的功能,当 Leader 服务器不可用,或者已经半数以上节点失去联系时,ZooKeeper 会进入恢复模式选举新的 Leader 服务器,使集群达到一个一致的状态。

共识问题:区块链如何确认记账权?

区块链的共识

区块链是一种去中心化的分布式账本系统,区块链的共识问题实际上是来源于分布式系统的一致性问题。
共识机制在区块链中扮演着核心的地位,共识机制决定了谁有记账的权利,以及记账权利的选择过程和理由。不同的虚拟货币采用共识机制也不同,常见的共识机制有 POW、POS、DPOS等。
Consistency 和 Consensus区别

  • Consistency 侧重的是内容在时间顺序上的一致和统一
  • Consensus 则是指由许多参与者对某项内容达成共识,所以一般把 Consistency 翻译为“一致性”,把 Consensus 翻译为“共识”。
拜占庭将军问题

一般在网络通信中,把节点故障,也就是信道不可靠的情况称为“非拜占庭错误”,恶意响应,也就是系统被攻击,传递错误消息称为“拜占庭错误”。
为什么叫拜占庭错误呢?实际上是来自于一个故事模型:

拜占庭帝国就是中世纪的土耳其帝国,拥有巨大的财富,周围 10 个邻邦垂诞已久,但拜占庭高墙耸立,固若金汤,没有一个单独的邻邦能够成功入侵。任何单个邻邦入侵都会失败,同时也有可能自身被其他 9 个邻邦入侵。
拜占庭帝国防御能力如此之强,至少要有十个邻邦中的一半以上同时进攻,才有可能攻破。然而,如果其中的一个或者几个邻邦本身答应好一起进攻,但实际过程出现背叛,那么入侵者可能都会被歼灭。
于是每一方都小心行事,不敢轻易相信邻国,这就是拜占庭将军问题。

在拜占庭问题里,各邻国最重要的事情是:所有将军如何能过达成共识去攻打拜占庭帝国。拜占庭将军问题核心描述是军中可能有叛徒,却要保证进攻一致,由此引申到计算机领域,发展成了一种容错理论:
一群将军想要实现某一个目标,比如一致进攻或者一致撤退,单独行动是行不通的,必须合作,达成共识;由于叛徒的存在,将军们不知道应该如何达到一致。

在记账权的归属中,关键的是如何避免恶意共识的出现,也就是错误的记账,类似如何处理拜占庭将军中的叛徒。

POW 工作量证明

PoW(Proof of Work,工作量证明)被认为是经过验证最安全的拜占庭解决机制,最早是用来防垃圾邮件的,典型的就是 Google 邮箱的反垃圾邮件系统。

Google 邮箱强制要求每一个给 Google 服务器发送邮件的发送者,必须先完成一定量的计算工作,造成一小段时间的延迟,比如延迟 1 秒,如果是正常的邮件发送,这个时间是可以接受;如果是广告邮件发送者,因为要进行大量的发送工作,这种无价值的计算是无法忍受的。

挖矿的由来

比特币挖矿是将一段时间内比特币系统中发生的交易进行确认,并记录在区块链上形成新区块的过程,由于需要竞争记账权,利用计算机去计算 Hash 数值,随机碰撞解题,这个过程就是挖矿。

换句话说,就是比特币系统出一道数学题,大家抢答最优解,挖矿就是记账的过程,矿工是记账员,区块链就是账本。

比特币的 POW 实现

比特币中的 POW 实现,是通过计算来猜测一个数值(Nonce),得以解决规定的 Hash 问题,下面是比特币的区块结构,可以看到区块头有个随机数字段,这个就是 Nonce 值:
在这里插入图片描述
中本聪在比特币系统中设置了一道题目,通过不断调节 Nonce 的值,来对区块头算 Hash,要求找到一个 Nonce 值,使得算出来的 Hash 值满足某个固定值。
具体的 Hash 方法一般是使用 SHA256 算法 ,你可以查看这个小工具来测试 https://tool.oschina.net/encrypt?type=2。
我们来简化一下计算过程,假设第 100 个区块给出的区块值是下列字符串,最早计算出该字符串的节点可以获得比特币:

f7684590e9c732fb3cf4bf0b8e0f5ea9511e8bbaacb589892634ae7938e5700c

由于 Hash 算法是一个不可以逆的算法,没法通过具体的 Hash 值倒推出原文,这样每个节点只能采用穷举的方法,也就是选择各种字符串,比如开始的 a、b、c、1、2、3、…,不断的尝试。
比特币系统自身会调节难度,控制解题的时间,一般来讲,约每 10 分钟挖出一个区块,在这 10 分钟内,计算机只能不停地去计算,去试各种字符串。
这个过程实际上是考验各个节点的服务器性能,也就是算力。如果你算力非常强大,有几万台服务器,可以很快得到 Nonce 值,也就是正确答案:lagou,对应 Hash 值和题目要求一致。
接下来你就可以把这个 Nonce 值放在结构体里,通过 P2P 网络广播出去,其他的系统节点收到后,发现这个 Nonce 值是合法的,能满足要求,会认为你挖矿成功。
由于解出了题目,你会获得系统对应的比特币奖励,以及本区块内所有交易产生的手续费。其他节点发现有人已经算出来了,就会放弃本次计算,然后开启下一个区块的题目,去寻找下一个区块头的 Nonce 值。
作为落地的最大区块链系统,比特币的区块信息一直在动态生成。下面这张截图记录了比特币最近的区块信息,区块信息来自 https://www.blockchain.com/,你也可以点击链接查看最新的区块高度。

区块链分叉和 51% 攻击

Hash 问题具有不可逆的特点,主要依靠暴力计算,谁的算力多,谁最先解决问题的概率就越大。当掌握超过全网一半算力时,就能控制网络中链的走向,这也是所谓 51% 攻击的由来。
前面我们说过,因为区块链中每个节点都可以参与记账,系统中可能出现链的分叉(Fork),最终会有一条链成为最长的链。

POW 机制优缺点

优点:POW 是第一个完全实现去中心化共识算法的,并且节点自由进出,容易实现,由于对算力的高要求,破坏系统花费的成本也巨大。
缺点最大的就是浪费能源,巨大的算力被浪费在了无尽的挖矿行为中,并且本身并不产生任何价值。

其他共识方法

除了 POW 机制,还有其他的共识方法,典型的就是 POS 和 DPOS 等。

POS 权益证明

POS(Proof of Stake,权益证明)类似现实生活中的股东大会机制,拥有股份越多的人拥有越多的投票权,也就越容易获取记账权。

POS 是通过保证金来对赌一个合法的块成为新的区块,收益为抵押资本的利息和交易服务费。提供证明的保证金越多,则获得记账权的概率就越大,合法记账者可以获得收益。著名的数字货币 ETH(以太坊),就在共识算法中采用了 POS 机制。

DPOS 委托权益证明

采用 DPOS(Delegated Proof of Stake,委托权益证明)机制的典型代表是 EOS,如果说 POS 类似股东大会,比较的是谁持有的股份多,那么 DPOS 类似于公司董事会制度,在 DPOS 共识制度下,会选出一定数量的代表,来负责生产区块。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值