分布式(二)

二、理论算法协议

1. CAP 理论

1.1 简介

又称作布鲁尔定理(Brewer’s theorem),分布式领域的定理。

(1)Consistency(一致性)

所有节点访问同一份最新的数据副本

(2)Availability(可用性)

非故障的节点在合理的时间内返回合理响应(不是错误或者超时的响应)。

(3)Partition Tolerance(分区容错性)

分布式系统出现网络分区,仍然能够对外提供服务。

什么是网络分区?
分布式系统中多个网络连通的节点,因为故障断开了导致整个网络分成了几块区域。

1.2 不是所谓“3 选 2”

1.2.1 常见错误

错误:致性、可用性、分区容错性三者你只能同时达到其中两个,不可能同时达到

正确:分区容错性是一定要满足的,在此基础上,只能满足可用性或者一致性。

1.2.2 架构

(1)分布式系统理论上不可能选择 CA 架构,只能选择 CP 或者 AP 架构。

CP架构:ZooKeeper、HBase

任何时刻对 ZooKeeper 的读请求都能得到一致性的结果,但是, ZooKeeper 不保证每次请求的可用性
如Leader 选举过程中或者半数以上的机器不可用的时候服务就是不可用的。

AP架构:Eureka、Cassandra

Eureka 保证即使大部分节点挂掉也不会影响正常提供服务,只要有一个节点是可用的就行了。
只不过这个节点上的数据可能并不是最新的。

Nacos 不仅支持 CP 架构也支持 AP 架构

(2)为啥不可能选择 CA 架构呢?
若系统出现“分区”,系统中的某个节点在进行写操作。
为了保证 C一致性, 必须要禁止其他节点的读写操作,这就和 A可用性 发生冲突了。
如果为了保证 A可用性,其他节点的读写操作正常的话,那就和 C一致性 发生冲突了。

(3)选择 CP 还是 AP ?

关键在于业务场景,如:于需要确保强一致性的场景如银行一般会选择保证 CP 。

(4)补充

如果网络分区正常(系统在绝大部分时候所处的状态),也就说不需要保证 P分区容错性 的时候,C一致性 和 A可用性 能够同时保证。

1.3 CAP 实际应用案例

以Dubbo注册中心为例(Dubbo架构图如下)

注册中心 Registry负责服务地址的注册与查找,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
在这里插入图片描述

总结:如果系统发生“网络分区”,我们要考虑选择 CP 还是 AP。如果系统没有发生“网络分区”的话,我们要思考如何保证 CA 。


2.BASE 理论

2.1 简介

(1)对CAP中一致性 C 和可用性 A 权衡的结果,来源对大规模互联网系统分布式实践的总结,大大降低了我们对系统的要求

(2)BASE:Basically Available(基本可用) 、Soft-state(软状态) 和 Eventually Consistent(最终一致性)

2.2 核心思想

(1)即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。

(2)本质上是对 CAP 中 AP 方案的一个补充。

AP 方案只是在系统发生分区的时候放弃一致性,而不是永远放弃一致性,在分区故障恢复后,系统应达到最终一致性。

2.3 BASE理论三要素

2.3.1 基本可用

分布式系统在出现不可预知故障的时候,允许损失部分可用性,但绝不是系统不可用。

(1)响应时间上的损失
如:正常情况下,处理用户请求需要 0.5s 返回结果,但是由于系统出现故障,处理用户请求的时间变为 3 s。

(2)系统功能上的损失
如:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的部分非核心功能无法使用。

2.3.2 软状态

(1)允许系统中的数据存在中间状态(CAP 理论中的数据不一致)

(2)并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。

2.3.3 最终一致性
(1)本质是需要系统保证最终数据能够达到一致,而不是需要实时保证系统数据的强一致性。
(2)分布式一致性3种级别

<1> 强一致性
系统写入了什么,读出来的就是什么。

<2> 弱一致性
不一定可以读取到最新写入的值,也不保证多少时间之后读取到的数据是最新的,只是会尽量保证某个时刻达到数据一致的状态。

<3> 最终一致性
弱一致性的升级版,系统会保证在一定时间内达到数据一致的状态。

(3)实现最终一致性的具体方式

<1> 读时修复
在读取数据时,检测数据的不一致,进行修复。

如:Cassandra 的 Read Repair 实现,在向 Cassandra 系统查询数据的时候,如果检测到不同节点 的副本数据不一致,系统就自动修复数据,

<2>写时修复(推荐:性能消耗较低)
在写入数据,检测数据的不一致时,进行修复。

如:Cassandra 的 Hinted Handoff 实现,Cassandra 集群的节点之间远程写数据的时候,如果写失败 就将数据缓存下来,然后定时重传,修复数据的不一致性。

<3> 异步修复
这个是最常用的方式,通过定时对账检测副本数据的一致性,并修复。

总结:ACID 是数据库事务完整性的理论,CAP 是分布式系统设计理论,BASE 是 CAP 理论中 AP 方案的延伸。


3.Paxos算法

3.1 介绍

第一个被证明完备的分布式共识算法

3.1.1 作用

让分布式系统中的多个节点对某个提案(Proposal)达成一致的看法。

提案:Leader节点是哪个、多个事件发生的顺序等

3.1.2 组成

(1)Basic Paxos 算法
描述的是多节点之间如何就某个值(提案 Value)达成共识。

(2)Multi-Paxos 思想
描述的是执行多个 Basic Paxos 实例,就一系列值达成共识实例。

说白了就是执行多次Basic Paxos,核心还是 Basic Paxos 。

3.1.3 改进

(1)Raft算法
Multi-Paxos的变种,简化了其思想,更容易理解及工程实现

(2)ZAB 协议 、 Fast Paxos 算法基于Paxos改进
针对没有恶意节点

(3)作量证明(POW,Proof-of-Work) 、 权益证明(PoS,Proof-of-Stake )也是基于Paxos改进
针对存在恶意节点

典型应用:区块链,比如以太坊官方宣布其共识机制正在从工作量证明(PoW)转变为权益证明(PoS)。

区块链系统使用的共识算法需要解决的核心问题是 拜占庭将军问题 ,这和我们日常接触到的 ZooKeeper、Etcd、Consul 等分布式中间件不太一样。

3.2 Basic Paxos 算法

3.2.1 3个重要角色

在这里插入图片描述

(1)提议者(Proposer)
也叫协调者(coordinator),负责接受客户端的请求并发起提案。

提案信息通常包括提案编号 (Proposal ID) 和提议的值 (Value)。

(2)接受者(Acceptor)
也叫投票员(voter),负责对提议者的提案进行投票,同时需要记住自己的投票历史。

(3)学习者(Learner)
如果有超过半数接受者就某个提议达成了共识,那么学习者就需要接受这个提议,并就该提议做出运算,然后将运算结果返回给客户端。

3.2.2 补充

(1)为了减少实现该算法所需的节点数,以上的一个节点可以身兼多个角色。

(2)一个提案被选定需要被半数以上的 Acceptor 接受。

(3)Basic Paxos 算法还具备容错性,在少于一半的节点出现故障时,集群仍能正常工作。

3.3 Multi Paxos 思想

(1)Basic Paxos 算法的仅能就单个值达成共识,为了能够对一系列的值达成共识,我们需要用到 Basic Paxos 思想。

(2)Multi-Paxos 只是一种思想,这种思想的核心就是通过多个 Basic Paxos 实例就一系列值达成共识。


4.Raft 算法

4.1 背景及示例

4.1.1 背景

(1)当今数据中心和应用程序通过服务器横向扩展,且要根据需求进行扩展和收缩,出现服务器和网络故障很常见。

(2)对客户来说,明显的中断通常是不可接受的。系统必须在正常操作期间处理服务器的上下线。它们必须对变故做出反应并在几秒钟内自动适应。

(3)分布式共识可以解决上面的问题。

4.1.2 示例:拜占庭将军

(1)问题
假设多位拜占庭将军中没有叛军,信使的信息可靠但有可能被暗杀的情况下,将军们如何达成是否要进攻的一致性决定?

(2)解决方案
先在所有的将军中选出一个大将军,用来做出所有的决定。

4.1.3 共识算法
4.1.3.1 共识是可容错系统中的一个基本问题:即使面对故障,服务器也可以在共享状态上达成一致。
4.1.3.2 适用于实际系统的共识算法特性:

(1)安全
保在非拜占庭条件下的安全性,包括网络延迟、分区、包丢失、复制和重新排序。

(2)高可用
大多数服务器都是可操作的,且可以互相通信,也可以与客户端通信,那么这些服务器就可以看做完全功能可用的

(3)一致性不依赖时序
错误的时钟和极端的消息延迟,在最坏情况下也只会造成可用性问题,而不会产生一致性问题

(4)在 集群中大多数服务器响应,命令就可以完成
不会被少数运行缓慢的服务器来影响整体系统性能

4.2 基础

4.2.1 节点类型

(1)Leader
负责发起心跳,响应客户端、创建日志、同步日志。

(2)Candidate
Leader选择过程中的临时角色,由Follower转化而来,发起投票参与竞选

(3)Follower
接受Leader的心跳和日志同步数据,投票给Candidate

备注: 在正常的情况下,只有一个服务器是 Leader,剩下的服务器是 Follower。Follower 是被动的,它们不会发送任何请求,只是响应来自 Leader 和 Candidate 的请求。
在这里插入图片描述

4.2.2 任期

如图:
在这里插入图片描述
(1)raft 算法将时间划分为任意长度的任期(term),任期用连续的数字表示,看作当前term号。

(2)每个任期开始就会选举并选出Leader,如果没有选出Leader就会立刻开始下一次选举直到选出。

(3)每个节点都会存储当前term号,服务器间通信会交换当前term号。
如果发现自己term号比其他人少就会更新到大的term值

如果一个Candidate 或者 Leader 发现自己的 term 过期了,就会立即退回Follower。

如果一台服务器收到的请求的term号是过期的,就会拒绝此次请求

4.2.3 日志

(1)entry
每一个时间成为entry,只有Leader可以创建entry。

entry内容为<term,index,cmd>,其中cmd可以应用到状态机的操作

(2)log
由entry构成的数组,每一个entry都有一个表明自己在log中的index。

只有Leader才可以改变其他节点的log。

entry总是先被Leader添加到自己的log数组中,然后放弃共识请求,获得同意后才被Leader提交给状态机

Follower 只能从 Leader 获取新日志和当前的commitIndex,然后把对应的entry应用到自己额状态机中

4.3 领导人选举

raft 使用心跳机制来触发 Leader 的选举。

(1)如果一台服务器能够收到来自 Leader 或者 Candidate 的有效信息,它会一直保持为Follower 状态,并且刷新自己的electionElapsed,重新计时。

(2)Leader 会向所有的 Follower周期性发送心跳来保证自己的Leader地位。
如果一个 Follower 在一个周期内没有收到心跳信息,就叫做选举超时。

然后它就会认为此时没有可用的Leader,并且开始进行一次选举以选出一个新的 Leader。

(3)为了开始新的选举,Follower 会自增自己的 term 号并且转换状态为 Candidate。

然后他会向所有节点发起 RequestVoteRPC 请求, Candidate 的状态会持续到以下情况发生:
<1> 赢得选举

<2> 其他节点赢得选举

<3> 一轮选举结束,无人胜出

(4)赢得选举的条件是:一个 Candidate 在一个任期内收到了来自来自集群内的多数选票(N/2+1),就可以成为 Leader。

(5)在 Candidate 等待选票的时候,它可能收到其他节点声明自己是Leader的心跳,此时有两种情况:
<1> 该 Leader 的 term 号大于等于自己的 term 号
说明对方已经成为 Leader,则自己回退为 Follower。

<2> 该 Leader 的 term 号小于自己的 term 号
那么会拒绝该请求并让该节点更新 term。

(6)raft 使用了随机的选举超时时间来避免无人获得选举并且无限重复选举
每一个 Candidate 在发起选举后,都会随机化一个新的枚举超时时间。

这种机制使得各个服务器能够分散开来。

在大多数情况下只有一个服务器会率先超时,它就会在其他服务器超时之前赢得选举。


4.4 日志复制

(1)一旦选出了 Leader,它就开始接受客户端请求。每一个客户端的请求都包含一条需要被复制状态机(Replicated State Mechine)执行的命令。

(2)Leader 收到客户端请求后,会生成一个 entry,包含<index,term,cmd>,再将这个 entry 添加到自己的日志末尾后,向所有的节点广播该entry,要求其他服务器复制这条entry。

(3)如果 Follower 接受该 entry,则会将 entry 添加到自己的日志后面,同时返回给Leader同意。

(4)如果 Leader 收到了多数的成功响应,Leader 会将这个 entry 应用到自己的状态机中,之后可以成为这个 entry 是 committed 的,并且向客户端返回执行结果。

(5)raft保证以下2个性质
<1> 在两个日志里,有两个 entry 拥有相同的 index 和 term,那么它们一定有相同的cmd
通过仅有Leader可以生成entry保证

<2> 在两个日志里,有两个 entry 拥有相同的 index 和 term,那么它们前面的entry也一定相同
需要一致性检查来保证

(6)一般情况下,Leader 和 Follower 的日志保持一致。
如果Leader 的崩溃会导致日志不一样,这样一致性检查会产生失败。

Leader 通过强制 Follower 复制自己的日志来处理日志的不一致。这就意味着,在 Follower 上的冲突日志会被领导者的日志覆盖。

为了使得 Follower 的日志和自己的日志一致,Leader 需要找到 Follower 与它日志一致的地方,然后删除 Follower 在该位置之后的日志,接着把这之后的日志发送给 Follower。

(7)Leader 给每一个Follower 维护一个nextIndex,表示Leader将要发送给该Follower一条日志条目的索引。

当一个Leader开始掌权是,它会将nextIndex初始化为它的最新的日志条目索引数+1。

如果一个Follower的日志和Leader的不一致,AppendEntries一致性检查会在下一次AppendEntries RPC时返回失败

在失败之后,Leader会将nextIndex递减然后重试AppendEntries RPC。

最终nextIndex会达到一个Leader和Follower日志一直的地方。这时,AppendEntries会返回成功,Follower中冲突的日志条目都被移除了,并且添加所缺少 的的上了 Leader 的日志条目。

一旦 AppendEntries 返回成功,Follower 和 Leader 的日志就一致了,这样的状态会保持到该任期结束。

4.5 安全性

4.5.1 选举限制

(1)Leader 需要保证自己存储全部已经提交的日志条目。
这样才可以使日志条目只有一个流向:从 Leader 流向 Follower,Leader 永远不会覆盖已经存在的日志条目。

(2)每个 Candidate 发送 RequestVoteRPC 时,都会带上最后一个entry的信息。
所有节点收到投票信息时,会对该 entry 进行比较,如果发现自己的更新,则拒绝投票给该 Candidate。

(3)判断日志新旧的方式:如果两个日志的 term 不同,term 大的更新;如果 term 相同,更长的 index 更新。

4.5.2 节点崩溃

(1)如果 Leader 崩溃,会触发新一轮选举。
集群中的节点在 electionTimeout 时间内没有收到 Leader 的心跳信息就会触发新一轮的选主,在选主期间整个集群对外是不可用的。

(2)如果 Follower 和 Candidate 崩溃,之后发送给它的 RequestVoteRPC 和 AppendEntriesRPC 会失败。

由于 raft 的所有请求都是幂等的,所以失败的话会无限的重试。

如果崩溃恢复后,就可以收到新的请求,然后选择追加或者拒绝 entry。

4.5.3 时间与可用性

(1)raft 的要求之一就是安全性不依赖于时间
系统不能仅仅因为一些事件发生的比预想的快一些或者慢一些就产生错误。

为了保证上述要求,最好能满足以下的时间条件:

broadcastTime << electionTimeout << MTBF

<1> broadcastTime
向其他节点并发送信息的平均响应时间

<2> electionTimeout
选举超时时间

<3> MTBF(mean time between failures)
单台机器的平均健康时间

(2)broadcastTime应该比electionTimeout小一个数量级,为的是使Leader能够持续发送心跳信息(heartbeat)来阻止Follower开始选举

(3)electionTimeout也要比MTBF小几个数量级,为的是使得系统稳定运行。

当Leader崩溃时,大约会在整个electionTimeout的时间内不可用;我们希望这种情况仅占全部时间的很小一部分。

(4)由于broadcastTime和MTBF是由系统决定的属性,因此需要决定electionTimeout的时间。
一般来说,broadcastTime 一般为 0.5~20ms,electionTimeout 可以设置为 10~500ms,MTBF 一般为一两个月。



上一篇跳转—分布式(一)                 下一篇跳转—分布式(三)


本篇文章主要参考链接如下:

参考链接1-JavaGuide


持续更新中…

随心所往,看见未来。Follow your heart,see light!

欢迎点赞、关注、留言,一起学习、交流!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值