本系列所有文章均为个人学习笔记所需,所以不会过多要求文章思路、不会对每段文字精雕细琢,只会随心所欲地记录想到的每个知识点,用自己最通俗的语言!各位看官千万忍住别拍砖,谢谢!
现如今的计算机理论中,分布式理论是很重要的一环,我们日常也总听到分布式、分布式架构等词汇,那么下文将针对这些名词进行探究,包括名词解释、相关理论知识、发展历程、在如今计算机实践中的重要性,等等。
先看看相关名词。
分布式名词概念
分布式
百度百科上,“分布式”即“分布式计算”:
- 所谓分布式计算就是在两个或多个软件互相共享信息,这些软件既可以在同一台计算机上运行,也可以在通过网络连接起来的多台计算机上运行
- 分布式计算是计算机科学中一个研究方向,它研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分,然后把这些部分分配给多个计算机进行处理,最后把这些计算结果综合起来得到最终的结果。
所以,分布式是一种计算方式,我们熟知的计算方式还有:集中式计算、并行计算、客户端-服务器计算、网格计算、云计算、边缘计算,等等。很显然,这些计算方式都有优缺点,都是为了解决计算的某些方面而提示的计算方式,例如简单、处理能力、可靠、可扩展、可伸缩等方面。而分布式计算的提出是为了解决单个计算机在处理能力、可靠性、可扩展性等方面的限制,以及为了更好地适应不断变化的计算需求和资源环境。随着时间的推移,这些需求和挑战进一步推动了分布式计算理论和技术的发展。本系列文章的核心就是探讨这些分布式计算理论和技术。
分布式架构
百度百科上:
- 分布式架构(Distributed Architecture)是分布式计算技术的应用和工具
所以,看起来满足“分布式计算”的应用和工具,都可以算是一种分布式架构。后边,我们挑当下最流行、未来有潜力的分布式架构探究探究。
这里出现“架构”的概念,这里特指“软件架构”,百度百科也有解释:“软件架构是指对软件系统的整体结构和组织方式进行设计和描述的过程。它关注的是系统的各个组件之间的关系、交互方式以及与外部环境的接口”。所以,我们在聊到分布式架构的时候,应该更关注整体结构和组织方式、都有哪些组件组成、各组件是关系、交互方式以及外部环境的接口。
分布式系统
百度百科上:
- 分布式系统(distributed system)是建立在网络之上的软件系统。
同样的,这里更精确的说是“分布式计算机系统”,还是百度百科:
- 分布式计算机系统是将多台小型微型机互连组成的一种新型计算机系统。它冲破了传统的集中式单机局面,从分散处理的概念出发来组织计算机系统,具有较高的性能价格比,灵活的系统可扩充性, 良好的实时性、可靠性与容错性等潜在优点
这么来看,分布式系统是一个实际运行的环境(某种意义上应该是按照分布式架构的风格组织起来的系统),更关注系统整体运行达到的性能、可靠性、容错性等特性。
了解了几个分布式的概念,那么我们就来详细看看这些概念所涉及的原理。
分布式基础
分布式特征
- 分布性:多台计算机在空间上随意分布,且随时都有可能发生变动
- 对等性:所有节点都是对等的,没有主从之分
- 自治性:所有节点都有自己的存储、计算能力,各节点都是平等的,可以自己完成计算、存储,也能通过网络共享数据、协调任务处理
- 并发性:分布式系统中的多个节点,可能并发地访问、操作相同的数据资源
分布式问题
- 缺乏全局时钟:因为没有一个全局时钟,所以很难定义两个事件的时间顺序
- 节点随时宕机:分布式系统中的任意节点,都可能随时发生宕机
- 网络异常:分布式网络环境是不稳定的,任何消息都无法保证完全可靠,可能发生消息丢失、乱序、错误等
- 分布式三态:任意两个节点的通信都可能出现三种状态:成功、失败、未知,分布式系统需要解决这三种状态
- 数据丢失:对于有状态节点,可能会发生数据丢失,就会导致状态丢失,如何处理?异常处理是大量实践检验过后比较有效的手段
CAP理论
- 一致性 (Consistency):一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据。所有节点访问同一份最新的数据。
- 可用性 (Availability):对数据更新具备高可用性,请求能够及时处理,不会一直等待,即使出现节点失效。
- 分区容错性 (Partition tolerance):能容忍网络分区,在网络断开的情况下,被分隔的节点仍能正常对外提供服务。
CAP中只能三选二,在现今的网络环境下,分区容错性是无法避免的,所以,分布式系统的设计通常会在一致性和可用性的选择上权衡。
当然,分区的情况虽然无法避免,但并不是很常见,所以,有的场景下考虑不存在分区的问题,从而使得一致性和可用性在某种程度上可以共存(不是水火不容的选择,例如很多分布式一致性算法就是这么干的,后边详细分析)。
BASE理论
- Basically Available(基本可用):分布式系统在出现不可预知故障的时候,允许损失部分可用性
- Soft state(软状态):软状态也称为弱状态,和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
- Eventually consistency(最终一致性):最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性
BASE理论可以看作是对CAP理论的一种实践方法,它接受一定时间的一致性放松,使得分布式系统在故障时仍具备可用性。在这段可容忍的时间段内,分布式系统处于软状态,但系统数据最终达成一致,我们通常需要关注这段时间的系统不一致状态,并做好处理,才能使得系统基本可用(Basically Available)。
ACID理论
不同于BASE理论是基于分布式场景的CAP理论的解决方案,ACID是一组数据库事务属性,确保数据库事务的可靠性和一致性,更多强调的是非分布式环境(如单机环境)。
Atomicity(原子性):事务是一个不可分割的整体,事务内所有操作要么全做成功,要么全失败
Consistency(一致性):事务执行前后,数据从一个状态到另一个状态必须是一致的(A向B转账,不能出现A扣了钱,B却没收到)
Isolation(隔离性):多个并发事务之间相互隔离,不能互相干扰
Durability(持久性):事务完成后,对数据库的更改是永久保存的,不能回滚
这是数据库系统逐步发展之后,总结的ACID原则,随后也发展出多项技术(并发控制、恢复机制和锁管理等)以实现ACID特性。后续会在MySQL相关章节再详细探讨具体的数据库技术原理。
康威定律
前些年微服务大火之后,康威定律也随之让大家认识,鉴于微服务是现如今最常见的分布式系统架构方式,所以这里也顺便聊聊康威定律。
原话:
Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations. - Melvin Conway(1967)
大体意思:设计系统的组织,其产生的设计等同于组织之内、组织之间的沟通结构。
所以,我们做的事情可能会决定我们微服务的拆分,从而影响团队的划分,当然也有因为团队组织结构而调整微服务结构的,总而言之,就是让组织和系统设计相匹配。另外微服务的边界,往往考虑到团队边界、业务边界,两者需要匹配(短期内可能会有团队之间的妥协,但不是最佳实践)。在微服务内部,可以自治管理,只需要定义清楚微服务的边界,以更好地与其他微服务/团队进行沟通。
分布式架构
面向服务架构(SOA,Service Oriented Architecture)
在微服务架构出现之前,通常的分布式架构为SOA,它将一个大系统拆分成多个子系统,各子系统之间通过企业服务总线(ESB,Enterprise Service Bus)通信,这整个网状系统就整理为星形结构,更清晰;其次,面向服务设计的方式,使得系统功能可以服用,企业能力也进一步高效使用。
微服务架构(MSA)
相比SOA,它更强调业务要彻底的“组件化”、“服务化”,即SOA把系统的功能拆分、通过总线通信组成一个整体可用的系统,而微服务架构则是形成一个个独立管理的子系统(去中心化),更关注按业务能力来划分服务及组织结构。尤其在docker容器化技术发展之后,微服务在部署实施方面更方便,这也促使微服务架构的快速发展和普及。
分布式算法
我们知道,分布式环境有网络延迟、节点故障、消息传递不确定性等各种问题,有分布式锁(保证分布式节点同一时刻只有一个节点修改数据)、分布式事务(确保多个节点的操作要么全部成功或者全部失败)、数据复制(多数据副本确保可靠性、可扩展)等解决方案,我们选择什么样的一致性模型(强一致、弱一致、最终一致等)决定了我们选择什么样的一致性方案。
这里,我们来探讨一下常见的一致性算法,后边再基于分布式基础组件来分别看看这些一致性算法的实际应用。
这里需要提一句,分布式系统通过多数据副本提高可靠性、扩展性等,更基础的理论可以看看1978年的经典论文《Time, Clocks, and the Ordering of Events in a Distributed System》,它的核心观点是:
- 系统内部,可以通过happen before确定不同事件的偏序,即根据逻辑时钟确定偏序
- 分布式环境实现物理时钟进行事件排序,非常难!而大部分场景下,逻辑时钟就能实现事件的排序(偏序)
- 逻辑时钟实现:每个节点初始化为0;每次发送事件附带时间戳并自增时间戳;收到消息时将时钟设置为本地时钟和消息时钟的最大值,再自增;
- 系统外部的事件偏序,可能导致逻辑时钟的异常行为,因此还需要根据物理时钟确定事件之间的偏序
- 物理时钟两大问题:时钟运行速率与真实时间有差异;任意两个时钟运行速率有差异;
- 物理时钟同步算法(TrueTime机制):考虑这两种差异,不断地微调本地的物理时钟,将差异控制在Strong Clock Condition范围内。
- Google的Spanner解决了这个问题:计算机时钟使用的是石英振荡器,精度不高、无法匀速推进,通常在真实时间左右波动(假设误差为±e);
- Spanner使用的是“Commit Wait”,即一个操作后等待2e时间再执行第二个操作,就能确保两个操作事件的物理时钟满足全局偏序;
- Google并没有透露太多Spanner实现细节,大致是通过一组time master节点分两部分分别装备GPS时钟和原子时钟(不一样的失效模型),其它节点为time slave节点,定期从time master节点同步时钟,即不断减小时钟误差,满足“Strong Clock Condition”即可
- 所以,只有通过“物理时钟”和“逻辑时钟”同时使用,才能保证事件全局偏序(相对论的时空偏序)
物理时钟的精确性很难实现,一般使用的是“逻辑时钟”+其它一致性算法来保证分布式系统的一致性。该论文还提到了状态机复制(SMR)的概念,将一致性问题转化为日志复制问题,其理论基础也是“事件时钟排序”理论。
一致性哈希
背景
单机应用通常使用传统的哈希算法来解决数据检索和存储的问题,特点是节点数量固定、数据存储位置确定、检索逻辑也就确定,这不难理解。但是在分布式环境下,节点数量的变化是经常发生的(扩容、节点失效等),此时需要各节点rebalancing,使用传统的哈希算法就会导致系统重新计算所有数据的哈希值、同时完成大量节点数据的迁移。
所以,通过环形哈希空间使得rebalancing过程尽可能减少节点数据的迁移,引入虚拟节点解决数据分布不均匀问题,优化哈希函数以减少哈希碰撞,动态调整环大小、节点位置以适应系统的负载和节点性能,引入备份节点以增强系统可靠性,等等。
下边,我们先看看评价一致性哈希好坏的四个衡量指标,再来看看一致性哈希的原理。
衡量指标
- 平衡性:数据应尽可能均匀的分布到各个节点上,使得各节点的负载差异尽可能的小(例如,100个用户的文件平均分配到5个节点,每个节点20个用户的数据)
- 单调性:增加或减少节点时,已分配到节点上的数据尽可能不动,只有新增节点会接收新数据、失效节点会迁移数据
- 分散性:也强调数据均匀分布到各节点上,但更强调的是数据的唯一性分布(例如,一个用户Bob存储100个文件,都分配到C节点上,当C节点发生故障则Bob所有的文件都无法访问,这就是分散性不好)
- 负载均衡:不同节点上分配请求和数据的机制,关注资源利用率
实现原理
- 定位数据?将所有节点构成一个虚拟的环形空间,每个数据哈希到环上的节点上,然后再顺时针找到最近的一个物理节点上
- 删除节点?将该节点上的数据迁移到下一个节点上(顺时针查找最近一个节点)
- 增加节点?将顺时针下一个节点的部分数据,迁移到新增节点上
上述操作可能会因为数据的迁移造成目标节点的压力瞬间增加,甚至引起雪崩(破坏平衡性指标)。
- 虚拟节点。在哈希环上增加多个虚拟节点并均匀地分布到物理节点上,这样数据在哈希环上就能均匀分配到物理节点上,这样可以缓解节点压力过大、系统雪崩的问题
在此之上还有很多优化点以解决分布式环境的各类问题。
Paxos
这个不用多说,Lamport大神提出的分布式一致性算法,公认解决分布式一致性最有效的算法,简单说是“分布式环境中的提议者(proposer)发起提案(proposal),系统中的大多数同意了该提案,则该提案生效。其中,最多只针对一个提案生效”。
三个角色:
- 提议者(Proposal):发起提案(proposal),包括提案编号(proposal id)和提案内容(value)
- 决策者(Acceptor):收到提案(proposal)后进行回应,可以同意接受该提案
- 学习者(Learner):不参与决策,只从提议者或决策者学习最新达成一致的提案
三个阶段:
- Prepare阶段:Proposer生成全局唯一且递增的Proposal ID,向所有Acceptors发送Prepare请求;Acceptors收到Prepare请求后,做出如下回复
- 不再接受Proposal ID小于等于当前请求的Prepare请求
- 不再接受Proposal ID小于当前请求的Propose请求
- 回复已经Accept过的提案中Proposal ID最大的那个提案的Value和Proposal ID,没有则返回空值
- Accept阶段:
- Proposer 收到多数Acceptors的Promise应答后,从应答中选择Proposal ID最大的提案的Value,携带当前Proposal ID,向所有Acceptors发送Propose请求
- Acceptor收到Propose请求后,接受并持久化当前Proposal ID和提案Value
- Learn阶段:Proposer在收到多数Acceptors的Accept之后,标志着本次Accept成功,决议形成,将形成的决议发送给所有Learners
可以看到Paxos执行过程不复杂,复杂的是Paxos算法的推导过程,这里可以从网上找相关文章学习(例如:https://zhuanlan.zhihu.com/p/684883113)。
Raft
相比Paxos的复杂、难懂,Raft的设计就是为了简单、易懂。简单来说,Raft是强leader机制(一旦某个follower没有收到leader消息,则变身candidate并发起选举,直至集群有一个明确的leader,才能进行下一步);有了leader则将客户端的请求写入日志,并将日志发送给所有follower(相当于发送提案过程);大多数follower确认接受日志后(即接受提案),则该日志生效,leader提交日志并更新状态机;若大多数follower并不接受日志,则leader需要删除该日志。
ZAB
ZAB即Zookeeper Atomic Broadcast(Zookeeper 原子广播协议),它是zk应用的分布式一致性协议。
ZAB与Raft有很多相似之处:Leader选举、Log复制、状态机、多数派原则、容错性等,核心不同点是ZAB是顺序处理客户端请求,即能确保全局严格的顺序性,当然在很多细节实现上也有很多的不同,这里不再赘述,后续深入具体中间件实现原理再来看。
总结
本文简要介绍分布式的基本概念以及相关算法,有了这些作为基础,我们后续逐个攻破分布式体系中的知识点,才能更深入的理解。
3525

被折叠的 条评论
为什么被折叠?



