极客时间之《分布式技术原理与算法》笔记

文|Seraph

分布式知识体系图
在一定资源上,进行一定通信,通过一定计算,完成一定数据的加工和处理,从而对外提供特定的服务

01 | 分布式缘何而起:从单兵,到游击队,到集团军

  1. 单机模式:性能受限、存在单点失效问题。
    在这里插入图片描述
  2. 游击队模式:数据并行或数据分布式
    第一步:将应用与数据分离
    在这里插入图片描述
    第二步:对数据进行拆分
    在这里插入图片描述
    存在的问题及解决办法:
  • 负载均衡:解决不同服务器效率不一致问题。
  • IO读写分离:解决数据库的IO访问成为瓶颈的问题。
  • 缓存机制:解决热点数据访问频繁问题。

主要的问题:对提升单个任务的执行性能及降低时延无效。(如单个任务比较复杂时,但执行次数少)

  1. 集团军模式:任务并行或任务分布式
    在这里插入图片描述
    面临的问题:设计比较复杂。

  2. 分布式其实就是将相同或相关的程序运行在多台计算机上,从而实现特定目标的一种计算方式。产生分布式的最主要驱动力量,是我们对于性能、可用性及可扩展性的不懈追求。

  3. 采用数据并行还是任务并行?
    任务执行时间短,数据规模大、类型相同且无依赖,则可采用数据并行;如果任务复杂、执行时间长,且任务可拆分为多个子任务,则考虑任务并行。

02 | 分布式系统的指标:啥是分布式的三围

  1. 分布式的目的是用更多的机器,处理更多的数据和更复杂的任务。性能、资源、可用性和可扩展性是分布式系统的重要指标。
  2. 性能指标:吞吐量(Throughput)、响应时间(Response Time)和完成时间(Turnaround Time))。
  3. 吞吐量指标有 QPS(Queries Per Second)、TPS(Transactions Per Second)和 BPS(Bits Per Second)
  4. 一个系统在没有任何负载时的资源占用,叫做空载资源占用,体现了这个系统自身的资源占用情况。对于同样的功能,空载资源占用越少,说明系统设计越优秀,越容易被用户接受。
  5. 一个系统满额负载时的资源占用,叫做满载资源占用,体现了这个系统全力运行时占用资源的情况,也体现了系统的处理能力。
  6. 系统的可用性可以用系统停止服务的时间与总的时间之比衡量。除此之外,系统的可用性还可以用某功能的失败次数与总的请求次数之比来衡量。
  7. 可靠性通常用来表示一个系统完全不出故障的概率,更多地用在硬件领域。而可用性则更多的是指在允许部分组件失效的情况下,一个系统对外仍能正常提供服务的概率。
  8. 可扩展性,指的是分布式系统通过扩展集群机器规模提高系统性能 (吞吐、响应时间、 完成时间)、存储容量、计算能力的特性,是分布式系统的特有性质。
  9. 垂直 / 纵向扩展指的是,增加单机的硬件能力,比如 CPU 增强、内存增大等;水平 / 横向扩展指的就是,增加计算机数量。
  10. 衡量系统可扩展性的常见指标是加速比(Speedup),也就是一个系统进行扩展后相对扩展前的性能提升。

03 | 分布式互斥:有你没我,有我没你

  1. 霸道总裁:集中式算法
    在这里插入图片描述
  • 协调者会成为系统的性能瓶颈。
  • 容易引发单点故障问题。
  1. 民主协商:分布式算法
    在这里插入图片描述
    在这里插入图片描述
    如上所示,每个程序都会自己维护一个队列,只需发送请求和答复请求功能即可。
    在分布式领域中,我们称之为分布式算法,或者使用组播和逻辑时钟的算法。
    缺点:
  • 问题1:可用性很低,在大型系统中使用分布式算法,消息数量会随着需要访问临界资源的程序数量呈指数级增加,容易导致高昂的“沟通成本”。
  • 问题2:一旦某一程序发生故障,无法发送同意消息,那么其他程序均处在等待回复的状态中,使得整个系统处于停滞状态,导致整个系统不可用。
    针对问题2的改进:如果检测到一个程序故障,则直接忽略这个程序,无需再等待它的同意消息。但这样就引来更大的复杂度。
    使用场景:适用于临界资源使用频度较低,且系统规模较小的场景。在这里插入图片描述
  1. 轮值 CEO:令牌环算法
    所有程序构成一个环结构,令牌按照顺时针(或逆时针)方向在程序之间传递,收到令牌的程序有权访问临界资源,访问完成后将令牌传送到下一个程序;若该程序不需要访问临界资源,则直接把令牌传送给下一个程序。
    在这里插入图片描述
    单点故障时,将令牌传送给故障点的下个节点,这样就需要每个节点知道所有节点。
    缺点:不需要访问资源的程序,也需要接收并传递令牌,会带来一些无效通信。

  2. 以上三种算法都只适用于规模小、节点数少的系统。可进一步了解:两层结构的分布式令牌环算法。
    在这里插入图片描述

04 | 分布式选举:国不可一日无君

  1. 主节点的存在,就可以保证其他节点的有序运行,以及数据库集群中的写入数据在每个节点上的一致性。但如果主节点故障,就会出现很大问题。
  2. 国不可一日无君,所以我们需要分布式选举的算法来选举主。
  3. 目前常见的选主方法:
  • 基于序号选举的算法:Bully 算法。
  • 多数派算法:Raft算法、ZAB算法。
  1. Bully算法(长者为大)
    选举原则:选取 ID 最大的节点作为主节点。
    Bully 算法在选举过程中,需要用到以下 3 种消息:
  • Election 消息,用于发起选举;
  • Alive 消息,对 Election 消息的应答;
  • Victory 消息,竞选成功的主节点向其他节点发送的宣誓主权的消息。

Bully 算法选举的原则是“长者为大”,意味着它的假设条件是,集群中每个节点均知道其他节点的 ID。在此前提下,其具体的选举过程是:

  • 集群中每个节点判断自己的 ID 是否为当前活着的节点中 ID 最大的,如果是,则直接向其他节点发送 Victory 消息,宣誓自己的主权;
  • 如果自己不是当前活着的节点中 ID 最大的,则向比自己 ID 大的所有节点发送 Election 消息,并等待其他节点的回复;
  • 若在给定的时间范围内,本节点没有收到其他节点回复的 Alive 消息,则认为自己成为主节点,并向其他节点发送 Victory 消息,宣誓自己成为主节点;若接收到来自比自己 ID 大的节点的 Alive 消息,则等待其他节点发送 Victory 消息;
  • 若本节点收到比自己 ID 小的节点发送的 Election 消息,则回复一个 Alive 消息,告知其他节点,我比你大,重新选举。
    在这里插入图片描述
    优点:选举速度快、算法复杂度低、简单易实现。
    缺点:需要每个节点有全局的节点信息,因此额外信息存储较多;其次,任意一个比当前主节点 ID 大的新节点或节点故障后恢复加入集群的时候,都可能会触发重新选举,成为新的主节点,如果该节点频繁退出、加入集群,就会导致频繁切主。
  1. Raft 算法(民主选举)
    选举原则:少数服从多数
    采用 Raft 算法选举,集群节点的角色有 3 种:
  • Leader,即主节点,同一时刻只有一个 Leader,负责协调和管理其他节点;
  • Candidate,即候选者,每一个节点都可以成为 Candidate,节点在该角色下才可以被选为新的 Leader;
  • Follower,Leader 的跟随者,不可以发起选举。

Raft 选举的流程,可以分为以下几步:

  • 初始化时,所有节点均为 Follower 状态。
  • 开始选主时,所有节点的状态由 Follower 转化为 Candidate,并向其他节点发送选举请求。
  • 其他节点根据接收到的选举请求的先后顺序,回复是否同意成为主。这里需要注意的是,在每一轮选举中,一个节点只能投出一张票。
  • 若发起选举请求的节点获得超过一半的投票,则成为主节点,其状态转化为 Leader,其他节点的状态则由 Candidate 降为 Follower。Leader 节点与 Follower 节点之间会定期发送心跳包,以检测主节点是否活着。
  • 当 Leader 节点的任期到了,即发现其他服务器开始下一轮选主周期时,Leader 节点的状态由 Leader 降级为 Follower,进入新一轮选主。
    节点状态迁移图
    优点:选举速度快、算法复杂度低、易于实现。
    缺点:系统内每个节点都可以相互通信,且需要获得过半的投票数才能选主成功,因此通信量大。但不会出现Bully算法那样的新节点加入频繁切主的情况。
  1. ZAB算法(具有优先级的民主投票)
    相较于 Raft 算法的投票机制,ZAB 算法增加了通过节点 ID 和数据 ID 作为参考进行选主,节点 ID 和数据 ID 越大,表示数据越新,优先成为主。
    使用 ZAB 算法选举时,集群中每个节点拥有 3 种角色:
  • Leader,主节点;
  • Follower,跟随者节点;
  • Observer,观察者,无投票权。
    选举过程中,集群中的节点拥有 4 个状态:
  • Looking 状态,即选举状态。当节点处于该状态时,它会认为当前集群中没有 Leader,因此自己进入选举状态。
  • Leading 状态,即领导者状态,表示已经选出主,且当前节点为 Leader。
  • Following 状态,即跟随者状态,集群中已经选出主后,其他非主节点状态更新为 Following,表示对 Leader 的追随。
  • Observing 状态,即观察者状态,表示当前节点为 Observer,持观望态度,没有投票权和选举权。

投票过程中,每个节点都有一个唯一的三元组 (server_id, server_zxID, epoch),其中 server_id 表示本节点的唯一 ID;server_zxID 表示本节点存放的数据 ID,数据 ID 越大表示数据越新,选举权重越大;epoch 表示当前选取轮数,一般用逻辑时钟表示。
选举过程中通过 (vote_id, vote_zxID) 来表明投票给哪个节点,其中 vote_id 表示被投票节点的 ID,vote_zxID 表示被投票节点的服务器 zxID。ZAB 算法选主的原则是:server_zxID 最大者成为 Leader;若 server_zxID 相同,则 server_id 最大者成为 Leader。
优点:稳定性比较好。
缺点:容易出现广播风暴。除了投票,还增加了对比节点 ID 和数据 ID,这就意味着还需要知道所有节点的 ID 和数据 ID,所以选举时间相对较长。

在这里插入图片描述
7. 多数派选主算法通常采用奇数节点。
在这里插入图片描述

05 | 分布式共识:存异求同

  1. 事务,其实是包含一系列操作的、一个有边界的工作序列,有明确的开始和结束标志,且要么被完全执行,要么完全失败,即 all or nothing。通常情况下,我们所说的事务指的都是本地事务,也就是在单机上的事务。
  2. 分布式事务,就是在分布式系统中运行的事务,由多个本地事务组合而成。
  3. ACID具体含义:
  • 原子性(Atomicity),即事务最终的状态只有两种,全部执行成功和全部不执行。
  • 一致性(Consistency),是指事务操作前和操作后,数据的完整性保持一致或满足完整性约束。
  • 隔离性(Isolation),是指当系统内有多个事务并发执行时,多个事务不会相互干扰。
  • 持久性(Durability),也被称为永久性,是指一个事务完成了,那么它对数据库所做的更新就被永久保存下来了。
  1. 强一致性 VS BASE理论
  2. 实现分布式事务有以下 3 种基本方法:
  • 基于 XA 协议的二阶段提交协议方法(强一致性)
  • 三阶段提交协议方法(强一致性)
  • 基于消息的最终一致性方法(BASE理论)
  1. 基于 XA 协议的二阶段提交方法
    XA 协议可以分为两部分,即事务管理器和本地资源管理器。
    事务管理器作为协调者,负责各个本地资源的提交和回滚;而资源管理器就是分布式事务的参与者,通常由数据库实现,比如 Oracle、DB2 等商业数据库都实现了 XA 接口。
    二阶段提交协议(The two-phase commit protocol,2PC),用于保证分布式系统中事务提交时的数据一致性。
    XA 在全局事务中用于协调多个资源的机制。
    两阶段提交协议的执行过程,分为
    投票(voting):
    在这里插入图片描述
    提交(commit):
    在这里插入图片描述
    缺点:
  • 同步阻塞问题:二阶段提交算法在执行过程中,所有参与节点都是事务阻塞型的。也就是说,当本地资源管理器占有临界资源时,其他资源管理器如果要访问同一临界资源,会处于阻塞状态。
  • 单点故障问题:基于 XA 的二阶段提交算法类似于集中式算法,一旦事务管理器发生故障,整个系统都处于停滞状态。
  • 数据不一致问题:在提交阶段,当协调者向参与者发送 DoCommit 请求之后,如果发生了局部网络异常,或者在发送提交请求的过程中协调者发生了故障,就会导致只有一部分参与者接收到了提交请求并执行提交操作,但其他未接到提交请求的那部分参与者则无法执行事务提交。
  1. 三阶段提交方法(Three-phase commit protocol,3PC)
    为了解决两阶段提交的同步阻塞和数据不一致问题,三阶段提交引入了超时机制和准备阶段。
    超时机制:如果协调者或参与者在规定的时间内没有接收到来自其他节点的响应,就会根据当前的状态选择提交或者终止整个事务。
    准备阶段:在第一阶段和第二阶段中间引入了一个准备阶段,也就是在提交阶段之前,加入了一个预提交阶段。在预提交阶段排除一些不一致的情况,保证在最后提交之前各参与节点的状态是一致的。
    3PC 把 2PC 的提交阶段一分为二,这样三阶段提交协议就有 CanCommit、PreCommit、DoCommit 三个阶段。
  • CanCommit 阶段
    在这里插入图片描述
  • PreCommit 阶段
    在这里插入图片描述
  • DoCommit 阶段
    在这里插入图片描述
    在 DoCommit 阶段,当参与者向协调者发送 Ack 消息后,如果长时间没有得到协调者的响应,在默认情况下,参与者会自动将超时的事务进行提交,不会像两阶段提交那样被阻塞住。
  1. 基于分布式消息的最终一致性方案
    2PC 和 3PC 这两种方法,有两个共同的缺点,一是都需要锁定资源,降低系统性能;二是,没有解决数据不一致的问题。
    基于分布式消息的最终一致性方案的事务处理,引入了一个消息中间件(Message Queue,MQ),用于在多个应用之间进行消息传递。
    在这里插入图片描述
    购物流程:
    在这里插入图片描述
  2. 三种方法对比
    在这里插入图片描述
  3. 刚性事务与柔性事务
    刚性事务,遵循 ACID 原则,具有强一致性。比如,数据库事务。
    柔性事务,其实就是根据不同的业务场景使用不同的方法实现最终一致性,也就是说我们可以根据业务的特性做部分取舍,容忍一定时间内的数据不一致。柔性事务的最终一致性,遵循的是 BASE 理论。
  4. BASE 理论
    BASE 理论包括:
    基本可用(Basically Available):分布式系统出现故障的时候,允许损失一部分功能的可用性。
    柔性状态(Soft State):在柔性事务中,允许系统存在中间状态,且这个中间状态不会影响系统整体可用性。
    最终一致性(Eventual Consistency):事务在操作过程中可能会由于同步延迟等问题导致不一致,但最终状态下,数据都是一致的。
    在这里插入图片描述

07 | 分布式锁:关键重地,非请勿入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章