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

文|MESeraph

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

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. 分布式共识的本质就是“存异求同”。
  2. 分布式共识就是在多个节点均可独自操作或记录的情况下,使得所有节点针对某个状态达成一致的过程。
  3. 分布式共识方法:
    分布式共识包括两个关键点,获得记账权和所有节点或服务器达成一致。
  • PoW(Proof-of-Work,工作量证明)
    PoW 算法,是以每个节点或服务器的计算能力(即“算力”)来竞争记账权的机制,因此是一种使用工作量证明机制的共识算法。
    PoW 机制的缺点也很明显,共识达成的周期长、效率低,资源消耗大。

  • PoS(Proof-of-Stake,权益证明)
    由系统权益代替算力来决定区块记账权,拥有的权益越大获得记账权的概率就越大。
    PoS 不需要消耗大量的电力就能够保证区块链网络的安全性,同时也不需要在每个区块中创建新的货币来激励记账者参与当前网络的运行,这也就在一定程度上缩短了达成共识所需要的时间。
    但PoS 算法中持币越多或持币越久,币龄就会越高,持币人就越容易挖到区块并得到激励,而持币少的人基本没有机会,这样整个系统的安全性实际上会被持币数量较大的一部分人掌握,容易出现垄断现象。

  • DPoS(Delegated Proof of Stake,委托权益证明)
    DPoS 算法的原理,类似股份制公司的董事会制度,普通股民虽然拥有股权,但进不了董事会,他们可以投票选举代表(受托人)代他们做决策。DPoS 是由被社区选举的可信帐户(受托人,比如得票数排行前 101 位)来拥有记账权。
    优点:DPoS 能耗更低,具有更快的交易速度。每隔一定周期会调整受托人,避免受托人造假和独权。
    缺点:在 DPoS 中,由于大多数持币人通过受托人参与投票,投票的积极性并不高;且一旦出现故障节点,DPoS 无法及时做出应对,导致安全隐患。

在这里插入图片描述
4. 一致性是指,分布式系统中的多个节点之间,给定一系列的操作,在约定协议的保障下,对外界呈现的数据或状态是一致的。
5. 共识是指,分布式系统中多个节点之间,彼此对某个状态达成一致结果的过程。
在这里插入图片描述

06 | 分布式事务:All or nothing

  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 | 分布式锁:关键重地,非请勿入

一、分布式锁简介
  1. 为了保证多个进程能看到锁,锁被存在公共存储(比如 Redis、Memcache、数据库等三方存储中),以实现多个进程并发访问同一个临界资源,同一时刻只有一个进程可访问共享资源,确保数据的一致性。
  2. 分布式锁的三种实现方法
  • 基于数据库实现分布式锁,这里的数据库指的是关系型数据库;
  • 基于缓存实现分布式锁;
  • 基于 ZooKeeper 实现分布式锁。
二、基于数据库实现分布式锁
  1. 当我们要锁住某个资源时,就在该表中增加一条记录,想要释放锁的时候就删除这条记录。
  2. 数据库需要落到硬盘上,频繁读取数据库会导致 IO 开销大,因此这种分布式锁适用于并发量低,对性能要求低的场景。
  3. 缺点
  • 单点故障问题。一旦数据库不可用,会导致整个系统崩溃。
  • 死锁问题。数据库锁没有失效时间,未获得锁的进程只能一直等待已获得锁的进程主动释放锁。一旦已获得锁的进程挂掉或者解锁操作失败,会导致锁记录一直存在数据库中,其他进程无法获得锁。
  • 仅适用于并发量低的应用。
三、基于缓存实现分布式锁
  1. 所谓基于缓存,也就是说把数据存放在计算机内存中,不需要写入磁盘,减少了 IO 读写。
  2. 以 Redis 为例:
  • 通常可以使用 setnx(key, value) 函数来实现分布式锁。
  • key 表示锁 id,value = currentTime + timeOut,表示当前时间 + 超时时间。也就是说,某个进程获得 key 这把锁后,如果在 value 的时间内未释放锁,系统就会主动释放锁。
  • setnx 函数的返回值有 0 和 1:返回 1,说明该服务器获得锁,setnx 将 key 对应的 value 设置为当前时间 + 锁的有效时间。返回 0,说明其他服务器已经获得了锁,进程不能进入临界区。该服务器可以不断尝试 setnx 操作,以获得锁。
  1. 相对于基于数据库实现分布式锁的方案来说,基于缓存实现的分布式锁的优势表现在以下几个方面:
  • 性能更好。数据被存放在内存,而不是磁盘,避免了频繁的 IO 操作。
  • 很多缓存可以跨集群部署,避免了单点故障问题。
  • 很多缓存服务都提供了可以用来实现分布式锁的方法。
  • 可以直接设置超时时间来控制锁的释放。
  1. 缺点:通过超时时间来控制锁的失效时间,并不是十分靠谱,因为一个进程执行时间可能比较长,或受系统进程做内存回收等影响,导致时间超时,从而不正确地释放了锁。
三、基于 ZooKeeper 实现分布式锁
  1. ZooKeeper 基于树形数据存储结构实现分布式锁,来解决多个进程同时访问同一临界资源时,数据的一致性问题。
  2. ZooKeeper 的树形数据存储结构主要由 4 种节点构成:
  • 持久节点。这是默认的节点类型,一直存在于 ZooKeeper 中。
  • 持久顺序节点。也就是说,在创建节点时,ZooKeeper 根据节点创建的时间顺序对节点进行编号。
  • 临时节点。与持久节点不同,当客户端与 ZooKeeper 断开连接后,该进程创建的临时节点就会被删除。
  • 临时顺序节点,就是按时间顺序编号的临时节点。
  1. ZooKeeper 基于临时顺序节点实现了分布锁。ZooKeeper 会采用如下方法来实现分布式锁:
  • 在与该方法对应的持久节点 shared_lock 的目录下,为每个进程创建一个临时顺序节点。
  • 每个进程获取 shared_lock 目录下的所有临时节点列表,注册子节点变更的 Watcher,并监听节点。每个节点确定自己的编号是否是 shared_lock 下所有子节点中最小的,若最小,则获得锁。例如,用户 A 的订单最先到服务器,因此创建了编号为 1 的临时顺序节点 LockNode1。该节点的编号是持久节点目录下最小的,因此获取到分布式锁,可以访问临界资源,从而可以购买吹风机。
  • 若本进程对应的临时节点编号不是最小的,则分为两种情况:
    a. 本进程为读请求,如果比自己序号小的节点中有写请求,则等待
    b. 本进程为写请求,如果比自己序号小的节点中有读请求,则等待。
  1. 缺点:虽然 ZooKeeper 实现的分布式锁,几乎能涵盖所有分布式锁的特性,且易于实现,但需要频繁地添加和删除节点,所以性能不如基于缓存实现的分布式锁。
四、三种实现方式对比

在这里插入图片描述

  1. 为了确保分布式锁的可用性,我们在设计时应考虑到以下几点:
  • 互斥性,即在分布式系统环境下,分布式锁应该能保证一个资源或一个方法在同一时间只能被一个机器的一个线程或进程操作。
  • 具备锁失效机制,防止死锁。即使有一个进程在持有锁的期间因为崩溃而没有主动解锁,也能保证后续其他进程可以获得锁。
  • 可重入性,即进程未释放锁时,可以多次访问临界资源。
  • 有高可用的获取锁和释放锁的功能,且性能要好。
五、其它
  1. 羊群效应,就是在整个分布式锁的竞争过程中,大量的“Watcher 通知”和“子节点列表的获取”操作重复运行,并且大多数节点的运行结果都是判断出自己当前并不是编号最小的节点,继续等待下一次通知,而不是执行业务逻辑。
    这,就会对 ZooKeeper 服务器造成巨大的性能影响和网络冲击。

  2. 解决方法:

  • 在与该方法对应的持久节点的目录下,为每个进程创建一个临时顺序节点。
  • 每个进程获取所有临时节点列表,对比自己的编号是否最小,若最小,则获得锁。
  • 若本进程对应的临时节点编号不是最小的,则继续判断:若本进程为读请求,则向比自己序号小的最后一个写请求节点注册 watch 监听,当监听到该节点释放锁后,则获取锁;若本进程为写请求,则向比自己序号小的最后一个请求节点注册 watch 监听,当监听到该节点释放锁后,获取锁。
    *在这里插入图片描述

08 | 分布式技术是如何引爆人工智能的?

  1. 人工智能的定义可以看出,数据、模型(也叫作算法)、算力是人工智能的三大核心。
    在一定程度上数据决定了机器学习的上限,而模型为逼近这个上限提供方法。
  2. 数据处理和模型训练是人工智能的关键技术,算力决定了数据处理和模型训练的实用性能,而分布式技术就是解决算力的不二妙招。
    在这里插入图片描述

09 | 分布式体系结构之集中式结构:一人在上,万人在下

  1. 什么是集中式结构?
    集中式结构就是,由一台或多台服务器组成中央服务器,系统内的所有数据都存储在中央服务器中,系统内所有的业务也均先由中央服务器处理。多个节点服务器与中央服务器连接,并将自己的信息汇报给中央服务器,由中央服务器统一进行资源和任务调度:中央服务器根据这些信息,将任务下达给节点服务器;节点服务器执行任务,并将结果反馈给中央服务器。

  2. 经典的集群管理系统:Google Borg、Kubernetes 和 Apache Mesos。

  3. Borg
    在这里插入图片描述

  4. Kubernetes
    Kubernetes 是 Google 开源的容器集群管理系统,是 Borg 的一个开源版本。Kubernetes 是用于自动部署、扩展和管理容器化应用程序的开源系统。其核心是,在集群的节点上运行容器化应用,可以进行自动化容器操作,包括部署、调度和在节点间弹性伸缩等。
    在这里插入图片描述

  5. Mesos
    Mesos 与 Borg 不同之处在于,Borg 的 Master 直接对接用户应用,也就是说用户可以向 Borg 的 Master 直接请求任务。但 Mesos 不可以,Mesos 只负责底层资源的管理和分配,并不涉及存储、 任务调度等功能,因此 Mesos Master 对接的是 Spark、Hadoop、Marathon 等框架,用户的任务需要提交到这些框架上。
    在这里插入图片描述

  6. 对比分析在这里插入图片描述

  7. master 和 slave之间其实可以通过TCP链接和心跳结合来进行判断。
    在这里插入图片描述

10 | 分布式体系结构之非集中式结构:众生平等

非集中式架构:服务的执行和数据的存储被分散到不同的服务器集群,服务器集群间通过消息传递进行通信和协调。

一、Akka集群
  1. Akka 框架基于 Actor 模型,提供了一个用于构建可扩展的、弹性的、快速响应的应用程序的平台。

在这里插入图片描述
2. Actor 模型为系统并发度提供了非常好的解决方案,且是一个异步的、非阻塞的、高性能的事件驱动编程模型。
3. 节点有 Leader 节点和非 Leader 节点之分。与非 Leader 节点相比,Leader 节点只是增加了负责节点的加入和移除集群的功能,所以并不会影响非集中式结构中节点的平等关系。
在这里插入图片描述
4. Akka 集群的创建过程

  • 种子节点。使用静态配置文件方式或者系统运行时指定方式,可以生成种子节点;种子节点是普通节点加入集群的联系点,可以自动接收新加入集群的节点的信息。
  • 首种子节点。首种子节点是配置文件中的第一个种子节点,其功能是集群第一次启动时,首种子节点启动起来,集群才能组建成功,保证集群第一次创建时只有一个集群。如下图 A 节点,就是 Akka 集群的首种子节点。
  • 普通节点。可以向种子节点或集群中的任意节点发送 Join 消息,请求加入集群。如下图的 B 和 C 节点,通过向 A 节点发送 Join 消息,从而加入到 Akka 集群。
    (Akka 集群采用了 Gossip 协议进行数据同步)
二、Redis 集群
  1. Redis集群架构
    在这里插入图片描述
  2. 在设计时,需要考虑数据的可靠性和分片存储问题
    可靠性:集群中每个节点均存在主备,也就是说每台服务器上都运行两个 Redis 服务,分别为主备,主故障后,备升主。
    分片存储问题:Redis 集群内置了 16384 个哈希槽,每个节点负责一部分哈希槽。当客户端要存储一个数据或对象时,对该对象的 key 通过 CRC16 校验后对 16384 取模,也就是 HASH_SLOT = CRC16(key) mod 16384 来决定哈希槽,从而确定存储在哪个节点上。
三、Cassandra 集群
  1. Cassandra 的集群架构与数据分片存储方案,与 Redis 集群类似。

  2. Cassandra 集群的系统架构是基于一致性哈希的完全 P2P 结构,没有 Master 的概念,所有节点都是同样的角色,彻底避免了因为单点问题导致的系统不稳定。
    在这里插入图片描述

  3. 在 Cassandra 集群中,每次客户端随机选择集群中的一个节点来请求数据,对应接收请求的节点将对应的 key 在一致性哈希环上定位出是哪些节点应该存储这个数据,然后将请求转发到对应的节点上,并将对应若干节点的查询反馈返回给客户端。

在这里插入图片描述
4. Gossip 是一种谣言传播协议,每个节点周期性地从节点列表中选择 k 个节点,将本节点存储的信息传播出去,直到所有节点信息一致,即算法收敛了。
减少重复消息解决方案:解决方案是,每个节点记录当前传输的消息且还未达到收敛的时候,已经发送给了哪些节点,然后每次选择时从没有发送过的节点列表中随机选择 k 个节点,直到所有节点均被传输或集群收敛为止。
在这里插入图片描述

11 | 分布式调度架构之单体调度:物质文明、精神文明一手抓

一、分布式调度
  1. 为用户任务寻找合适的服务器这个过程,在分布式领域中叫作调度。
  2. 不同的分布式架构的调度器原理也不一样,最常见或最直观的是单体调度,就是任务和分布式系统中的空闲资源直接进行匹配调度。
二、单体调度
  1. 分布式系统中的单体调度是指,一个集群中只有一个节点运行调度进程,该节点对集群中的其他节点具有访问权限,可以搜集其他节点的资源信息、节点状态等进行统一管理,同时根据用户下发的任务对资源的需求,在调度器中进行任务与资源匹配,然后根据匹配结果将任务指派给其他节点。

  2. 采用单体调度集群:Google Borg、Kubernetes。

  3. 调度过程:
    在这里插入图片描述

  4. 单体调度设计:
    在这里插入图片描述
    在集群管理中,单体调度模块称为“Scheduler”或“单体调度器”。单体调度器也叫作集中式调度器,指的是使用中心化的方式去管理资源和调度任务。

  5. Borg 调度设计
    一个 Borg 作业的属性包括名称、拥有者和任务个数。作业可以有一些约束来强制其任务运行在有特定属性的机器上,比如处理器架构、操作系统版本、是否有外网 IP 地址等。这些约束可以是硬性的也可以是柔性的,其中柔性约束表示偏好,而非需求。一个作业只在一个集群中运行。
    一个作业可以包含多个任务。作业类似于用户在一次事务处理或计算过程中要求计算机所做工作的总和,而任务就是一项项具体的工作,二者属于包含关系。
    多个任务可以在多台机器上同时执行,从而加快作业的完成速度,提高系统的并行程度。而具体将哪个任务分配给哪个机器去完成,就是调度器要做的事儿了。
    在这里插入图片描述
    Scheduler 负责任务的调度,当用户提交一个作业给 BorgMaster 后,BorgMaster 会把该作业保存到 Paxos 仓库中,并将这个作业的所有任务加入等待队列中。调度器异步地扫描等待队列,将任务分配到满足作业约束且有足够资源的计算节点上。
    Borg调度算法:

  • 可行性检查,找到一组可以运行任务的机器(Borglet);
  • 评分,从可行的机器中选择一个合适的机器(Borglet)。
    常见的评分算法:“最差匹配”和“最佳匹配”。
三、集体联邦
  1. 集群联邦,就是将多个集群联合起来工作,核心思想是增加一个控制中心,由它提供统一对外接口,多个集群的 Master 向这个控制中心进行注册,控制中心会管理所有注册集群的状态和资源信息,控制中心接收到任务后会根据任务和集群信息进行调度匹配,选择到合适的集群后,将任务发送给相应的集群去执行。

在这里插入图片描述

12 | 分布式调度架构之两层调度:物质文明、精神文明两手抓

一、两层调度
  1. 两层调度结构对应的就是两层调度器,资源的使用状态同时由中央调度器和第二层调度器管理,中央调度器从整体上进行资源的管理与分配,将资源分配到第二层调度器;再由第二层调度器负责将资源与具体的任务配对,因此第二层调度可以有多个调度器,以支持不同的任务类型。
    在这里插入图片描述
  2. 采用两层调度结构的集群管理系统有很多,典型代表是 Apache Mesos 和 Hadoop YARN。
二、两层调度设计
  1. 具体到两层调度架构上,Mesos 本身实现的调度器为第一层调度,负责资源管理,然后将第二层任务调度交给了框架完成。
    在这里插入图片描述
三、资源分配算法
  1. 最大最小公平算法(Max-min Fairness,MMF)
    3 个主要原则:
    按照用户对资源需求量递增的顺序进行空闲资源分配;
    不存在用户得到的资源超过自己需求的情况;
    对于分配的资源不满足需求的用户,所获得的资源是相等的。
    实列:
    假设,现在有总量为 100 的空闲资源,有 4 个用户 A、B、C、D 对该资源的需求量分别为(35,10,25,45),分配流程如下所示:
  • 按照用户对资源的需求量升序排列,则 4 个用户的需求量为(B:10,C:25,A:35,D:45)。
  • 平均分配空闲资源。资源空闲总量 100,除以用户数 4,则平均空闲资源量为 25;按照第一步中需求量分配后,用户资源需求量为(0,0,10,20),且用户 B 由于资源需求量小于 25,因此会剩余资源。此时空闲资源量为 15,资源需求人数为 2。
  • 重复第二步,平均分配资源,15/2=7.5,即分别为用户 A 和 D 分配 7.5 份资源,此时用户资源需求量为(0,0,2.5,12.5),空闲资源量为 0,资源需求人数为 2。
  • 所有资源已分配完,算法终止。
  1. 主导资源公平算法
    最大最小公平算法采用了绝对公平的方式分配资源,会导致大量的资源浪费,比如用户需求量为 35 和 45 的用户 A 和用户 D。
    主导资源公平算法首先计算已经分配给用户的每一种资源的占用率(Resource Share),比如已经分配的 CPU 占总资源量的多少,已经分配的内存占总资源量的多少。所有资源占用率中的最大值称作该用户的主导资源占用率,而主导资源占用率对应的资源就是用户的主导资源。
    在这里插入图片描述
  2. 最大最小公平算法适用于单一类型的资源分配场景,而主导资源公平算法适用于多种类型资源混合的场景。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/pengshuyes/article/details/105505179