分布式理论 | 青训营笔记

162 阅读9分钟

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

分布式概述

什么是分布式

Why? How? What

常见的分布式系统

系统模型

故障模型

按照故障处理难度进行划分。

  • Byzantine failure:节点可以任意篡改发送给其他节点的数据,是最难处理的故障
  • Authentication detectable byzantine failure (ADB):节点可以篡改数据,但不能伪造其他节点的数据
  • Performance failure:节点未在特定时间段内收到数据,即时间太早或太晚
  • Omission failure:节点收到数据的时间无限晚,即收不到数据
  • Crash failure:节点停止响应,持续性的故障
  • Fail-stop failure:错误可检测,是最容易处理的故障

总结 故障处理难度从低到高

image.png

其中 Fail-stop 是出错并且知道原因、Crash是出错但是不知道原因。

Omission和Performance都是未决状态,但是Omission明确是个故障,而Perforamance是故障和非故障的叠加态,真正的未决。

而对于最后两个拜占庭问题,都是正确性方面的故障,不知道数据是真的还是假的,解决起来难度太大,一般的分布式系统不予以解决,而是通过加密等方式来保证信息不会被篡改。

常见故障类型划分

image.png

拜占庭将军问题

拜占庭两将军问题

简述

拜占庭帝国的两个将军率领军队与敌军作战,两只部队中间夹着敌军,且单独一只军队进攻对军一定会失败,需要两军互相派出通信兵通信,协商统一进攻时间。但是通信兵穿越敌军的过程中可能会被俘虏,导致通信过程受阻。问,需要派出多少通信兵,才能保证两者协商一致。

解答

无论派出多少通信兵,两者都不能够协商一致。

因为,假如A派出通信兵与B协商,B收到后派出通信兵告诉A说同意了,但是通信兵被截获了,B出兵了,A却没有,没有达成共识。而A如果再加一次通信(三次握手),但是A此时出兵了,如果A派出的通信兵迟迟没有到,B仍然不会出兵。达不成共识。

工程解

两个解决方案(将出错可能降到最小)

  • 一次派出N个通信兵,总有一个能够到
  • 设置超时重传,一段时间没收到回复,就重发。

比如 TCP 就是通过 三次握手 + 重传机制,给出了拜占庭问题的工程解。

拜占庭将军问题(三人及以上)

拜占庭帝国有多个将军,每个将军独立的观察敌军,并给了投降 / 进攻的投票,最后汇总结果,根据占比半数以上的方案实施。

但是这些将军中间有叛徒,叛徒会篡改发给其他将军的消息。导致投票结果出错。

解答

对于 3 m + 1 个将军,其中有m个叛徒,可以通过 m 次协商可以达到共识。

比如4个将军A、B、C、D,其中有一个叛徒,而D将军只负责统计票数,没有投票权。

第一轮协商时,A、B、C将自己的选择交由D将军,由D将军统计结果,并将结果发还给A、B、C。

之后,A、B、C进行第二轮投票。

这样操作之后,无论D是不是叛徒,最后都一定可以达成共识。

因为

假如 D 是叛徒,那么D发给A、B、C的消息可能是错的,因为消息可能会被篡改,又因为只有一个叛徒,所以,A、B、C都是忠臣,那么第二轮协商时,没有叛徒了,一定可以得到正确的结果。

假如D 是忠臣,并且只有一个叛徒,那么D发给A、B、C的消息,起码有2个是正确的,再第二轮协商时,投票环节,两个正确的票大于叛徒手里那一张票,所以也可以得到正确的结果。

大部分的分布式系统,都没有解决拜占庭问题(区块链解决了)。

共识和一致性

共识

多个服务器间通过协商,达成共同约定,就叫做共识。

最终一致性

所有的数据最终读到的都是一致的。也就是发生修改后,一段时间内,其他节点读到的数据可能是旧的,也可能是新的,但是最终都会读到最新的数据。

线性一致性

只要有一个服务器读到最新的数据,就会立马同步给其他所有客户端,不会有数据摇摆这种情况的发生。此外,线性的意思是,读到的数据是连续的,不中断,不回退的。不会有客户端读到了新数据,之后还有客户端读到老数据这种数据回退情况发生。

时间和事件顺序

Happen Before

image.png

  • 在同一节点,如果该节点上的A事件发生在B事件之前,那么就是说 A -> B
  • 在不同节点,如果A事件发送一个消息,B事件接受一个消息,那么也可以说 A -> B
  • 对于 A -> B -> C,有A -> C。当且仅当,A 不happenbeforeB,并且B 不happenbofore A的时候,才说A、B是并发的。

可以通过这条原则,推导不同节点上的事件的 happenbefore 关系。

lamport逻辑时钟

image.png

对于每个节点Pi,我们都定义一个(事件的函数)时钟函数Ci,它为任意的事件a赋值为Ci(a),也就是x的值是事件编号,y是lamport时间戳。

并规定

  • a -> b,那么一定有Ci(a) < Ci(b)
  • b -> a,那么一定有Ci(a) > Ci(b)

image.png

如图,可以在图中加入虚线(tick line)

要求

  • tick line之间的时间间隔一致
  • 一个节点的 tick line 中只能有一个事件。

理论基础

CAP理论

简介

  • C 一致性
  • A 可用性
  • P 分区容错性 分区中没有办法同时具有百分百具备CAP,三个特性。

划分

CA

放弃分区容错性,比如单机数据库。

CP

放弃绝对的可用性,保证一致性。常用于金融、钱财相关的应用。

AP

放弃绝对的一致性(弱一致性),保证可用性。常用于注重用户体验的产品。

应用

常用在数据库领域,以及分布式存储领域。

工程解

提供服务的多个节点,其中一个节点为 Master 节点,负责处理所有请求,其余节点为 backup 节点,只负责备份 Master 节点同步过来的数据。Master 节点会在检查点时,将自身数据同步给 backup 节点。

当 Master 节点出现故障时,可以直接切换 backup 节点为新的 Master 节点,代替 Master 节点处理请求。中间切换需要时间,但可以保证一定的可用性。

而如果Master出现故障时,检查点之前的数据已经同步给backup服务器,数据自然不会丢失,但检查点之后写入的数据会丢失。也就保证了一定的一致性。

ACID理论 CA系统

BASE理论 AP系统

简介

BASE理论是大型互联网公司分布式实践的总结,是通过CAP理论逐渐演变过来的。BASE理论适用于AP系统,也就是注重可用性,因为大部分不与钱财相关的公司,都用不到那么高的可用性。

内容

  • Basically Available 基本可用
    • 假设系统发生了不可预知的错误,但是还是能用,只是可能服务降级。
  • Soft State 软状态
    • 允许系统中出现中间状态,也就是允许不同的客户端访问到不同的数据(新、旧数据)
  • Eventually Consistent 最终一致性
    • 最终所有客户端都能访问到新的数据。

分布式事务 CP系统

二阶段提交

简介

二阶段提交是分布式事务的一种实现方式。

前置条件

  • 节点有两个角色,Coordinator(协调者) 和 Participant(参与者)
  • 所有节点都采用预写式日志,且日志写入完成后会被记录在可靠介质上
  • 所有节点都不会永久损坏,也就是损坏后都能修复

过程

image.png 提交分两个阶段:

  • Prepare阶段
    • 协调者会向参与者发送Prepare请求。
    • 参与者收到Prepare请求,并进行处理。
    • 如果处理成功,会发回给协调者 Done 响应。
    • 如果处理失败,会发回 Fail 响应。
  • Commit阶段
    • 协调者根据 Prepare 阶段返回的请求,选择回退还是提交。
      • 如果第一阶段所有参与者返回的都是Done,选择提交。
      • 如果第一阶段任一参与者响应Fail,选择回退。
    • 选择回退,会向参与者发送 Rallback 请求。
    • 选择提交,会向参与者发送 Commit 请求。
    • 参与者执行完后会向协调者发送 ACK 响应。

可能遇到的问题

  • 参与者宕机、协调者未宕机。
    • 二阶段提交的第二阶段,协调者会发送 Roolback 请求进行回滚
  • 参与者未宕机,协调者宕机。
    • 会重新选择新的协调者
  • 参与者和协调者都宕机。
    • 需要数据库管理员手动管理。

缺点

  • 性能开销大
    • 两阶段提交需要访问多个节点,带来额外开销
  • 协调者单点故障
    • 协调者一旦宕机,需要另起一个协调者,中间会造成服务停摆。
  • 网络分区问题
    • 一旦部分参与者收到了Commit请求,一部分参与者没收到?这时候只能选择回滚,会造成数据不一致,只能回滚。(一般事务提交过程全程加锁,拒绝读操作的,所以这部分中间数据不会被读到,但是会造成阻塞问题)

思考

  • 如何满足第二个前置要求,将预写日志保存到可靠介质上
    • 因为分布式可能使用廉价服务器,所以不从硬件方面解决,大多数解决方案都是使用分布式文件存储系统,KV存储系统。
  • 如果有的ACK收到了,有的没收到,怎么办
    • 回滚。

三阶段提交

简介

二阶段提交的优化版,不过只是缓解了二阶段提交遇到的问题

阶段

  • CanCommit
    • 询问是否可执行CanCommit,是,继续,不是(节点发生故障),结束/推出。
  • PreCommit
    • 询问是否可执行PreCommit,是,继续,不是,RollBack。
  • DoCommit
    • 执行,向所有节点提交事务,并接收ACK

改进

因为提交事务前,会先询问事务是否可以被执行,如果是,才执行,这就避免了很多,事务加锁并执行到最后阶段,才发现问题,需要重做事务,要节省非常多的内存。

缺点

  • 性能
  • 网络分区问题

MVCC

共识协议

Quorum NWR模型

RAFT模型

Paxos模型

分布式实践

MapReduce

分布式KV