分布式理论-现代架构基石直播课 | 青训营笔记

86 阅读19分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天

这里主要是分布式系统理论的介绍。课前部分主要罗列课程中涉及到的概念。对于不熟悉的概念,同学们可以提前查询预习;课中部分主要罗列每一部分的关键思路,帮助同学们跟上课程的进度;课后部分是一些问题,帮助同学们在课后梳理本课程的重点。

分布式概述

  • 分布式系统是计算机程序的集合,这些程序利用跨多个独立计算节点的计算资源来实现共同的目标。可以分为分布式计算、分布式存储、分布式数据库等。

  • 优势:

    • 去中心化
    • 低成本
    • 弹性
    • 资源共享
    • 可靠性高
  • 挑战:

    • 普遍的节点故障
    • 不可靠的网络
    • 异构的机器与硬件环境
    • 安全

image-20230131100649116

Why-How-What

  • 使用者视角:

    • Why:

      • 数据爆炸,存算大规模挑战
      • 成本低,廉价服务器集群
    • How:

      • 分布式框架
      • 成熟分布式系统
    • What:

      • 规模,负载,一致性要求等
      • 稳定性要求&技术方案
  • 学习者视角:

    • Why:

      • 后端开发必备技能
      • 帮助理解后台服务器之间协作的机理
    • How:

      • 掌握分布式理论
      • 了解一致性协议
    • What :

      • 把要点深入展开,针对难点搜索互联网资料进行学习
      • 将所学知识运用于实践

常见分布式系统

  • 分布式存储:

    • Google File System ( GFS): google分布式文件系统
    • Ceph: 统一的分布式存储系统
    • Hadoop HDFS: 基于GFS架构的开源分布式文件系统
    • Zookeeper: 高可用的分布式数据管理与系统协调框架
  • 分布式数据库:

    • Google Spanner: google可扩展的、全球分布式的数据库。
    • TiDB: 开源分布式关系型数据库
    • HBase: 开源Nosq|数据库
    • MongoDB :文档数据库
  • 分布式计算:

    • Hadoop: 基于MapReduce分布式计算框架
    • Spark: 在Hadoop基础之上,使用内存来存储数据
    • YARN: 分布式资源调度

系统模型

故障模型

  • Byzantine failure :节点可以任意篡改发送给其他节点的数据
  • Authentication detectable byzantine failure (ADB) :Byzantine failure的特例;节点可以篡改数据,但不能伪造其他节点的数据
  • Performance failure :节点未在特定时间段内收到数据,即时间太早或太晚
  • Omission failure :节点收到数据的时间无限晚,即收不到数据
  • Crash failure :在omission failure的基础上,增加了节点停止响应的假设,也即持续性地omission failure
  • Fail-stop failure :在Crash failure的基础上增加了错误可检测的假设
  • 根据故障处理的难易程度划分:

image-20230131101820495

大多数分布式系统是不解决拜占庭故障的。怎么解决?加密&冗余设计,没法保证100%不被篡改,但是能检测出来。

  • 各种故障问题:

image-20230131102234327

拜占庭将军问题

  • 引入:两将军问题( Two Generals' Problem) : 两支军队的将军只能派信使穿越敌方领土互相通信,以此约定进攻时间。该问题希望求解如何在两名将军派出的任何信使都可能被俘虏的情况下,就进攻时间达成共识。——来自于wikipedia。

结论是,两将军问题是被证实无解的电脑通信问题,两支军队理论.上永远无法达成共识。

  • 方案一: 同时发送N个信使,任何一个达到对方军队,都算成功。
  • 方案二:设置超时时间,发送后未在一定时间返回,则加派信使。
  • 共识与消息传递的不同:即使保证了消息传递成功,也不能保证达成共识。
  • TCP三次握手是在两个方向确认包的序列号,增加了超时重试,是两将军问题的一个工程解。
  • 思考:

    • 为何三次握手?而不是两次和四次?
    • 挥手过程中,如果FIN报文丢失,发生什么?

三个将军的问题

  • 拜占庭将军考虑更加普适的场景,例如3个将军ABC互相传递消息,消息可能丢失,也可能被篡改,当有一个将军是“叛徒" ( 即出现拜占 庭故障)时,整个系统无法达成致。
  • 如果没有"叛徒”, 无论各自观察到怎样的敌情,总能达成一致的行动。由于"叛徒" C的存在将军A和将军B获得不同的信息。 这样将军A获得2票进攻1票撤退的信息,将军B获得1票进攻2票撤退的信息,产生了不一致。
  • 考虑当4个将军,只有1个叛徒的场景。将军D作为消息分发中枢,约定如果没收到消息则执行撤退。如果D为"叛徒" ABC无论收到任何消息,总能达成一致
  • D为“忠将” , ABC有2人将D的消息进行正确的传递,同样能保证最终决策符合大多数。进而能够证明,当有3m+1个将军,其中m个“叛徒”时,可以增加m轮协商,最终达成一致

image-20230131103214068

共识和一致性

  • 客户端A读到x=0 ,当客户端C正在写入时 客户端A和B可能读到0或者1。但是当C写 入完成后,A和B最终能读到一致的数据。 我们称这样的一致性为Eventually Consistent (最终一致性)

image-20230131103641391

  • 当客户端A读到更新的版本x=1后,及时将 消息同步给其他客户端,这样其他客户端 立即能获取到x=1。我们称这样的一致性为 Linearizability (线性一致性)
  • 如果要保证“线性”一致性, 多个节点间 势必需要进行协商,以寻求一致。这样增 加了延迟,系统可用性便会受损

image-20230131103726587

等同于强一致性

时间和事件顺序

image-20230131103854446

1978年Leslie Lamport岌表在Communications of the ACM.上的洽文Time, Clocks, and the Ordering of Events in a Distributed System

我们定义"nappenedbefore" 关系, 记为"->"。其満足如下三个条件:

  • 如果a和b是在相同节点上的两个事件a在b之前友,则定义: a -> b
  • 如果事件a表示某个节点发送某条消息,b是男一个节点接受文条消息,則有a -> b
  • 如果有a -> b 且 b -> c ,則有a -> c。当且仅当a+b且b+a吋, 我們称兩个事件カ并岌的(concurrent).我們不雉在圉中找到若干満足条件的事件対,例如p1-r4 ,其由p1-q2- -q4- +r3一r4推导而来

逻辑时钟

  • Lamport逻辑时钟
  • 对于每一个节点Pi我们定义时钟Ci为一个函数,它为任意的事件a赋值编号为Ci(a)
  1. 如果a和b是在相同节点Pi上的两个事件,a在b之前发生,则有Ci(a><Ci<b)
  2. 如果事件a表示节点Pi发送某条消息,b表示节点Pj接受这条消息,则有Ci(a><Gj<b)
  • 于是我们可以在时空图中加入类似右图虚线所示的"tick line"
  • 在同一节点内的连续两个事件之间,至少要有一条tick line
  • 利用逻辑时钟,我们可以对整个系统中的事件进行全序排序

image-20230131104235193

时间是离散的,不是连续的昂!

遇到的问题:逻辑时钟和物理时钟不一致,你没办法保证物理时钟一致啊orz。

理论基础

CAP

image-20230131104437173

  • CAP理论往往运用于数据库领域,同样可以适用于分布式存储方向:

    • CA:放弃分区容错性,加强一致性和可用性,其实就是传统的单机数据库的选 择。
    • AP:放弃一致性(这里说的一致性是强一致性),追求分区容错性和可用性, 例如一些注重用户体验的系统。
    • CP:放弃可用性,追求一致性和分区容错性,例如与钱财安全相关的系统。

image-20230131104524099

  • 取舍:

image-20230131104717105

上面P1, P2并行的,下面是主备的,虽然CA都损失了一点,但是都保证了很多昂!!!

ACID

事务是数据库系统中非常重要的概念,它是数据库管理系统执行过程中的一个逻辑单元,它能够保证一个事务中的所有操作要么全部执行,要么全都不执行。 ​ 数据库事务拥有四个特性ACID ,即分别是原子性( Atomicity)、一致性( Consistency)、隔离性( Isolation )和持久性(Durability )

  • 原子性(A)。原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。
  • 一致性(C)。一致性是指事务必须使数据库从一 个一致性状态变换到另一个一致性状态,也就是说一个事务执行 前和执行之后都必须处于一致性状态。

这个一致性和上面CAP里面的一致性不一致哈,这个一致性是事务的一致性,上面的一致性是信息的一致性昂!!!

  • 隔离性(I)。隔离性是当多个用户并发访问数据库时,数据库为每一个用户开启的事务 ,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
  • 持久性(D)。持久性是指一个事务一旦被提交了 ,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

image-20230131105127965

Base

  • Base理论是对CAP中一致性和可用性权衡的结果,其来源于对大型互联网分布式实践的总结,是基于CAP定理逐步演化而来的。其核心思想是:

    • Basically Available(基本可用) :假设系统,出现了不可预知的故障,但还是能用,相比较正常的系统而言:响应时间.上的损失,或功能上的损失.
    • Soft state (软状态) : 允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点 的数据副本存在数据延时。
    • Eventually consistent (最终一致性 ) : 系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一 致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值。

image-20230131105523514

分布式事务

两阶段提交

二阶段提交( Two-phase Commit) : 为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种演算法。

  • 三个假设:

    1. 引入协调者( Coordinator )和参与者( Participants), 互相进行网络通信
    2. 所有节点都采用预写式日志,且日志被写入后即被保持在可靠的存储设备上
    3. 所有节点不会永久性损坏,即使损坏后仍然可以恢复

image-20230131110732273

  • 可能出现的情况:

    • 情况1 ) Coordinator不宕机, Participant宕机。如下图所示,需要进行回滚操作
    • 情况2 ) Coordinator宕机,Participant不宕机。可以起新的协调者,待查询状态后,重复二阶段提交
    • 情况3 ) Coordinator宕机,Participant宕机。

回滚:在Prepare阶段,如果某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。

image-20230131110919460

情况三:无法确认状态,需要数据库管理员的介入,防止数据库进入一个不一致的状态

  • 两阶段提交需注意的问题:

    1. 性能问题:两阶段提交需要多次节点间的网络通信,耗时过大,资源需要进行锁定,徒增资源等待时间。
    2. 协调者单点故障问题:如果事务协调者节点宕机,需要另起新的协调者,否则参与者处于中间状态无法完成事务。
    3. 网络分区带来的数据不一致:部分参与者收到了Commit消息,另一部分参与者没收到Commit消息,会导致了节点之间数据不一致。
  • 思考:

    1. 日志被保存在「可靠」的存储设备上。如何保证这一点?
    2. 参与者Commit了,但Ack信息协调者没收到。怎么办?

三阶段提交

三阶段提交Vs两阶段提交

  • 将两阶段提交中的Prepare阶段,拆成两部分: CanCommit和PreCommit机制

CanCommit避免阻塞和资源浪费,事务操作很重的,先看看,省的再rollback昂,麻烦了。可以做,再去做!

  • 解决了两个问题:

    1. 单点故障问题
    2. 阻塞问题

另外引入超时机制,在等待超时之后,会继续进行事务的提交。

思考?

三阶段缓和了两阶段面临的问题,但依然没有解决:

  1. 性能问题
  2. 网络分区场景带来的数据一致性问题

image-20230131111659366

MVCC

image-20230131111903086

MVCC是一 种并发控制的方法, 维持一个数据的多个版本使读写操作没有冲突。所以既不会阻塞写, 也不阻塞读。MVCC为每个修改保存一个版本, 和事务的时间戳相关联。可以提高并发性能,解决脏读的问题。

image-20230131112132793

时钟强同步,如何强同步?可以购买设备,和卫星强同步哇!!!(依赖硬件就是问题,不能指望用户有这个能力去购买硬件啊)

  • 另外一种时间戳的实现:时间戳预言机( TSO ), 采用中心化的授时方式,所有协调者向中心化节点获取时间(类似于Zookeeper拿了个锁嘛哈哈哈哈哈,我也想的是这种昂)。方法简单,实现方便,但需要每个节点都与他进行交互,会产生一些网络通信的成本。 TSO的授时中就需要考虑性能以及更好的容错性。

image-20230131112518821

共识协议

Quorum NWR模型

Quorum NWR三要素

N: 在分布式存储系统中,有多少份备份数据 W: 代表次成功的更新操作要求至少有w份数据写入成功 R: 代表一次成功的读数据操作要求至少有R份数据成功读取

为了保证强一致性,需要保证W+R > N(必要非充分条件)

Quorum NWR模型将CAP的选择交给用户,是一种简化版的一致性模型。

image-20230131112652106

  • 思考:

引起的并发更新问题 读者如果读到副本1和副本2 , 得出v= 3的结论 如果读到副本2和副本3,得出v= 2的结论

问题根源:允许数据被覆盖

image-20230131112739811

W, R可以动态调整,根据你对于CAP应用场景的预期进行处理。

RAFT协议

Raft协议是一种分布式一 致性算法 (共识算法), 即使出现部分节点故障,网络延时等情况,也不影响各节点,进而提高系统的整体可用性。Raft是使用较为广泛的分布式协议。一定意义上讲,RAFT也使用了Quorum机制。

  • Leader:领导者,通常一个系统中是一 主( Leader )多从( Follower)。Leader 负责处理所有的客户端请求,并向Follower同步请求日志当日志同步到大多数节点上后 ,通知Follower提交日志。
  • Follower:跟随者, 不会发送任何请求。接受并持久化Leader同步的日志,在Leader告知日志可以提交后,提交日志。当Leader出现故障时,主动推荐自己为Candidate.
  • Candidate:备选者, Leader选举过程中的临时角色。向其他节点发送请求投票信息。如果获得大多数选票, 则晋升为Leader。

image-20230131113223038

  • Log(日志) : 节点之间同步的信息,以只追加写的方式进行同步,解决了数据被覆盖的问题
  • Term (任期号) :单调递增,每个Term内最多只有一个Leader
  • Committed :日志被复制到多数派节点,即可认为已经被提交
  • Applied :日志被应用到本地状态机:执行了log中命令,修改了内存状态

image-20230131113303895

  • Leader选举过程:

    1. 初始全部为Follower

    2. Current Term + 1

    3. 选举自己

    4. 向其它参与者发起RequestVote请求retry直到:

    • 收到多数派请求,成为Leader,并发送心跳
    • 收到其它Leader的请求,转为Follower,更新自己的Term
    • 收到部分 ,但未达到多数派 ,选举超时 ,随机timeout开始下一 轮
  • 两个规则:

    • 在一个任期内每个参与者最多投一票(持久化)
    • 要成为Leader ,必须拿到多数投票
  • Log Replication过程:

新Leader产生, Leader和Follower不同步,Leader强制覆盖Followers的不同步的日志

  1. Leader收到写请求w

  2. 将w写入本地log

  3. 向其它Follower发起AppendEntries RPC

  4. 等待多数派回复

    • 更新本地状态机,返回给客户端
    • 下一个心跳通知Follower上一个Log已经被Committed了
    • Follower也根据命令应用本地状态机
  5. Follower有问题,Leader-直retry

如果Leader有问题呢?

  • 切主:

当Leader出现问题时,就需要进行重新选举。

  1. Leader发现失去Follower的响应,失去Leader身份。
  2. 两个Follower之间一段时间未收到心跳,重新进行选举,选出新的Leader,此时发生了切主
  3. Leader自杀重启,以Follower的身份加入进来

问题:老leader未失去身份,新leader已经选出,产生了“双主”,该如何解决呢?

image-20230131114150141

  • Stale读:

发生Leader切换,old leader收到了读请求。如 果直接响应,可能会有Stale Read。如何解决?

解决方案,保证读的强一致

读操作在lease timeout内默认自 己是leader ; 不是则发起一次heartbeat。 等待Commit Index 应用到状态机。

Election timeout > lease timeout :新leader.上 任,自从上次心跳之后一定超过了Election timeout , 旧leader大概率能够发现自己的Lease 过期。

Paxos协议

Paxos算法与RAFT算法区别:

  1. Multi-Paxos可以并发修改日志,而Raft写日志操作必 须是连续的
  2. Multi-Paxos可以随机选主,不必最新最全的节点当选Leader
  • Paxos优势: 写入并发性能高,所有节点都能写入
  • Paxos劣势: 没有一个节点有完整的最新的数据,恢复流程复杂,需要同步历史记录

image-20230131114523570

image-20230131114556125

分布式实践

MapReduce

image-20230131114736628

  • 容错:

    • Mapper故障: 由中心化节点重新发起调度,新起Mapper重跑job
    • Reducer故障: 重跑Mapper,代价大

Mapper: 将输入分解为多个Job来并行处理。彼此间几乎没有依赖关系 Shuffler: 将maper结果打乱,防止数据倾斜 Reducer: 对map阶段的结果进行全局汇总

分布式KV

  • 架构: 将海量结构化数据根据Key分成不同的Region,每个Region构建一个单机KV数据库,Region之间形成Raft Groups 做到强一致
  • 容错: 当Node故障时,通过Raft Learner模式进行数据修复
  • 弹性: 当出现局部Key热点或数据膨胀时, Region可以进行Split操作,分成两个子Region,反之收缩时进行Merge操作.

image-20230131115039528

课后问题

  1. 分布式系统有哪些优势和挑战?
  2. 两将军问题为什么理论上永远达不成共识?
  3. 为什么TCP采用三次握手?而不是两次和四次?
  4. 为什么在4将军问题中,增加1轮协商就可以对抗拜占庭故障?
  5. 什么是最终一致性?什么是线性一致性?
  6. CAP理论中,请举例说明可用性和一致性的矛盾?
  7. 数据库里的一致性和分布式系统中的一致性有什么区别?
  8. 两阶段提交中,什么场景需要数据库管理员介入?
  9. 三阶段提交缓和两阶段提交的哪两个问题?
  10. 什么场景适合乐观锁?什么场景适合悲观锁?
  11. 在共识协议中,为什么说允许数据被覆盖会带来数据一致性问题?
  12. RAFT协议中,Leader写成功日志Log20但未同步给Followers后宕机,Follower重新选举后产生一条新日志Log20,这时Leader重启,整个系统发现两种不一样的Log20的记录,请问如何区分并拒掉前面的Log20?
  13. RAFT协议中,Stale读是如何产生的?该如何解决Stale读的问题?

作者:青训营官方账号 链接:juejin.cn/post/719336… 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

References:

  1. 上课内容对应文档材料:juejin.cn/post/719336…