08 分布式理论 | 青训营笔记

275 阅读15分钟

08 分布式理论 | 青训营笔记

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

分布式理论 -- 现代架构基石, 基础架构-池化存储

讲师: 董乘宇

bytedance.feishu.cn/file/boxcn4…

分布式概述

什么是分布式

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

 优势:
     1 去中心化
     2 低成本
     3 弹性
     4 资源共享
     5 可靠性高
 挑战:
     1 普遍的节点故障
     2 不可靠的网络
     3 异构的机器与硬件环境
     4 安全

Why-How-What

 使用者视角
 Why:
     1 数据爆炸, 对存储和计算有大规模运用的述求
     2 成本低, 构建在廉价服务器之上
 How:
     1 分布式框架
     2 成熟的分布式系统
 What:
     1 理清规模, 负载, 一致性要求等
     2 明确稳定性要求, 制定技术方案
 学习者视角⭐
 Why:
     1 后端开发必备技能
     2 帮助理解后台服务器之间协作的机理
 How:
     1 掌握分布式理论
     2 了解一致性协议
 What:
     1 把要点深入展开, 针对难点探索互联网进行学习
     2 将所学知识运用于实践

常见的分布式系统

 分布式存储
     1 Google File System(GFS): Google分布式文件系统
     2 Ceph: 统一的分布式存储系统
     3 Hadoop HDFS: 基于GFS架构的开源分布式文件系统
     4 Zookeeper: 高可用的分布式数据管理与系统协调框架
 分布式数据库
     1 Google Spanner: Google可扩展的, 全球分布式的数据库
     2 TiDB: 开源分布式关系型数据库
     3 HBase: 开源Nosql数据库
     4 MongoDB: 文档数据库
 分布式计算
     1 Hadoop: 基于MapReduce分布式计算框架
     2 Spark: 在Hadoop基础之上, 使用内存来存储数据
     3 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的基础上增加了错误可检测的假设

故障|描述|可能的类型
磁盘故障 | 如: 磁头不寻道, 盘片不转, 磁介质损伤. 年发生率1~2% | Fail-stop
磁盘坏道, 坏块 | 磁头划伤引起坏道, 或受宇宙射线影响晶体管产生位反转 | Fail-stop, ADB
服务器主板, 板卡故障 | 可能是风扇故障, 或灰尘引起的短路, 或SCSI/RAID卡造成的死机 | Crash
网络故障 | 电源故障, 背板故障等, 网卡位反转, 网络流量大造成大量丢包等 | Byzantine, Omission
网络分区 | 网络引起节点形成不同的子集, 子集中网络相通, 子集间网络不同 | Performance
内存故障 | 内存出错造成的数据被篡改, 分为UE, CE两种 | ADB
线缆故障 | 服务器光模块频繁up或down | Performance, Omission
内核崩溃 | 内核内部的致命, 产生的kernel panic | Crash
CPU故障 | 年故障率接近1% | Omission | Crash
电源故障 | 服务器失去电力支撑 | Omission
软件故障 | 如: 进程crash, 内存踩坏, 状态不一致, 配置错误, 软件bug等 | Byzantine, Crash等

拜占庭将军问题

 引入: 两将军问题(Two Generals's Problem): 两支军队的将军只能派信使穿越敌方领土互相通信, 以此约定进攻时间. 该问题希望求解, 如何在两名将军派出的任何信使都可能被俘虏的情况下, 就进攻时间达成共识. 
 结论: 两将军问题是被证实无解的电脑通信问题, 两支军队理论上永远无法达成共识
           
 优化方案:
 一: 同时发送N个信使, 任何一个到达对方军队, 都算成功
 二: 设置超时时间, 发送后未在一定时间返回, 则加派信使
 这些措施只能增加概率, 不能保证达成共识
           
 共识与消息传递不同: 即时保证消息传递成功, 也不能达成共识
 工程解: TCP三次握手加超时重试, 近似解决了拜占庭将军问题, 这是所有问题的基础

思考:
1 为何是三次握手, 不是两次或四次?
2 挥手过程中, 如果FIN报文丢失, 发生什么?

引入: 三将军问题
结论: 有叛徒存在时, 无法达成一致. 无叛徒存在时, 总能达成一致
当有3m+1个将军时, 其中m个叛徒, 可以增加m轮协商, 最终达成一致\

 一般分布式系统不会去考虑消息被篡改, 是非拜占庭容错的
比特币考虑了, 具有拜占庭容错

共识和一致性

 最终一致性
 线性一致性 (强一致性)
 如果保证线性一致性, 需要多节点进行协商, 会增加延迟, 系统可用性降低

时间和事件顺序

Lamport

论文Time, Clocks, and the Ordering of Events in a Distribute System

理论基础

CAP理论

 选项 | 描述
 C (Consistence): 一致性, 指数据在多个副本之间能够保持一致的特性 (严格的一致性)
 A (Availability): 可用性, 指系统提供的服务必须一直处于可用的状态, 每次请求都能获取到非错的响应, 但是不保证获取的数据为最新数据
 P (Network partitioning): 分区容错性, 分布式系统在遇到任何网络分区故障的时候, 仍然能够对外提供满足一致性和可用性的服务, 除非整个网络环境都发生了故障
 CAP理论往往运用于数据库领域, 同样可以适用于分布式存储方向
 无法完全满足CAP, 需进行权衡
 CA: 放弃分区容错性, 加强一致性和可用性, 其实就是传统的单机数据库的选择
 AP: 放弃一致性(这里指强一致性), 追求分区容错性和可用性, 例如一些注重用户体验的系统
 CP: 放弃可用性, 追求一致性和分区容错性, 例如与钱财安全相关的系统

ACID理论

CA

 事务是数据库系统中非常重要的概念, 它是数据库管理系统执行过程中的一个逻辑单元, 它能够保证一个事务中的所有操作要么全部执行, 要么全都不执行

数据库事务有四个特性ACID, 分别是原子性(Atomicity), 一致性(Consistency), 隔离性(Isolation), 和持久性(Durability)
原子性(A): 原子性是指事物包含的所有操作要么全部成功, 要么全部失败
一致性(C): 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态, 也就是一个事务执行之前和执行之后都必须处于一致性状态 (和CAP理论的一致性意思不同)
隔离性(I): 隔离性是当多个用户并发访问数据库时, 数据库为每个用户开启的事务, 不能被其他事务的操作所干扰, 多个并发事务之间要相互隔离
持久性(D): 持久性是指一个事务一旦被提交了, 那么对数据库中的数据的改变就是永久性的, 即便在数据库系统遇到故障的情况下也不会丢失提交事务的操作

BASE理论

AP

 Base理论是对CAP中一致性和可用性权衡的结果, 来源于对大型互联网分布式实践的总结, 是基于CAP定理逐步演化而来的. 其核心思想是:
     Basically Available(基本可用): 假设系统出现了不可预知的故障, 但还是能用, 相比较正常的系统而言; 响应时间上的损失, 或功能上的损失
     Soft state(软状态): 允许系统中的数据存在中间状态, 并认为该状态不影响系统的整体可用性, 即允许系统在多个不同节点的数据副本存在数据延时
     Eventually consistent(最终一致性): 系统能够保证在没有其他新的更新操作的情况下, 数据最终一定能够达到一致的状态. 因此所有客户端对系统的数据访问最终能够获取到最新的值

分布式事务

CP

两阶段提交

 两阶段提交(Two-phase Commit): 为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种演算法
     三个假设:
         1 引入协调者(Coordinator)和参与者(Participants), 互相进行网络通信
         2 所有节点都采用预写式日志, 且日志被写入后即被保持在可靠的存储设备上
         3 所有节点不会永久性损坏, 即时损坏后仍然可用恢复
     Prepare阶段
     Commit阶段
 可能的情况:
     1 Coordinator不宕机, Participant宕机. 进行回滚操作
     2 Coordinator宕机, Participant宕机, 可用启用新的Coordinator, 重新进行两阶段提交
     3 Coordinator和Participant都宕机, 需要数据库管理员介入, 防止数据库进入不一致的状态

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

思考?
1 日志被保存在可靠的存储设备上, 如何保证这一点?
2 参与者Commit了, 但Ack信息协调者没收到, 怎么办?
回滚整个事务

三阶段提交

将两阶段提交中的Prepare阶段, 拆成两部分:
CanCommit和PreCommit机制
解决了两个问题:
1 单点故障问题
2 阻塞问题
另外引入了超时机制, 在等待超时之后, 会继续进行事务的提交

思考?
三阶段缓和了两阶段的部分问题, 但依然没有解决
1 性能问题
2 网络分区场景带来的数据一致性问题

MVCC

悲观锁: 操作数据时直接把数据锁住, 直到操作完成后才会释放锁; 上锁期间其他人不能修改数据 乐观锁: 不会上锁, 只是在执行更新时判断别人是否修改数据, 只有冲突时才会放弃操作

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

共识协议

Quorum NWR模型

 N: 在分布式存储系统中, 有多少份备份数据
 W: 代表一次成功的更新操作要求至少有w份数据写入成功
 R: 代表一次成功的读数据操作要求至少有R份数据成功读取
 为了保证强一致性, 需要保证W+R>N (这是必要条件, 不是充分条件)
 Quorum NWR模型将CAP的选择交给用户
 思考:
     引起的并发更新问题
     问题根源: 允许数据被覆盖, 不允许即可避免

RAFT协议

Raft协议是一种分布式一致性算法(共识算法), 即时出现部分节点故障, 网络延时等情况, 也不影响各节点, 进而提高系统的整体可用性. Raft是使用较为广泛的分布式协议. 一定意义上讲, RAFT也使用了Quorum机制
Leader - 领导者, 通常一个系统是一主(Leader)多从(Follower). Leader负责处理所有的客户端请求, 并向Follower同步请求日志, 当日志同步到大多数节点上后, 通知Follower提交日志
Follower - 跟随者, 不会发送任何请求, 接受并持久化Leader同步的日志, 在Leader告知日志可用提交后, 提交日志. 当Leader出现故障时, 主动推荐自己为Candidate
Candidate - 备选者, Leader选举过程中的临时角. 向其他节点发送请求投票信息. 如果获得大多数选票, 则晋升为Leader

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

 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出现问题时, 就需要进行重新选举
     1 Leader发现失去Follower的响应, 失去Leader身份
     2 两个Follower之间一段时间未收到心跳, 重新进行选举, 选出新的Leader, 此时发生了切主
     3 Leader自杀重启, 以Follower的身份加入进来
 问题: 老Leader未失去身份, 新Leader已经选出, 产生了双主, 如何解决
 Stale读: 发生Leader切换, old leader收到了读请求, 如果直接响应, 可用会有Stale Read. 如何解决
 解决方法: 新Leader上任, 要在上次心跳或Election timeout后, 即旧Leader的Lease过期. 避免双主

Paxos协议

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

分布式实践

MapReduce

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

分布式KV

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

思考题汇总

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