这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天
分布式概述
简介
分布式系统是计算机程序的集合,这些程序利用跨多个独立计算节点的计算资源来实现共同的目标。可以分为分布式计算、分布式存储、分布式数据库等。
常见分布式系统
分布式存储
-
GFS
-
Ceph
-
Hadoop HDFS: Based on GFS
-
Zookeeper
分布式数据库
-
Google Spanner
-
TiDB: SQL
-
HBase: NoSQL
-
MongoDB: doc SQL
分布式计算
-
Hadoop: Based on MapReduce
-
Spark: Based on Hadoop, it uses memory to save data
-
YARN
系统模型
故障模型
-
Byzantine failure: Nodes can arbitrarily tamper with the data sent to other nodes
-
Authentication detectable byzantine failure (ADB): Nodes can tamper with data, but cannot falsify data of other nodes
-
Performance failure: No response at a certain time
-
Omission failure: Long time no response
-
Crash failure: Known errors
-
Fail-stop failure: Known errors and reasons
真实故障
拜占庭将军问题
一般使用数据加密的手段避免拜占庭将军问题,而不是通过协议解决此问题
共识和一致性
最终一致性
读请求和写请求并发时可能读到旧值
线性一致性
增加了协商的过程,也就增加了延迟,系统可用性会受损
时间和事件顺序
In 1978, Leslie Lamport published "Time, Clock, and the Ordering of Events in a Distributed System" at Communications of the ACM
理论基础
CAP (Consistency, Availability, Network partitioning)
CAP 理论往往运用于数据库领域,同样可以适用于分布式存储方向。
一般而言C, A, P 三者不能同时实现,所以会有三种模型:
-
CA: 放弃分区容错性,是一般传统单机数据库的选择
-
AP: 放弃一致性(这里特指强一致性),追求分区容错性和可用性,常用于一些注重用户体验的系统
-
CP: 放弃可用性,追求一致性和分区容错性,例如与钱财安全相关的系统
ACID 理论
A: 原子性,事务要么全部操作成功,要么全部回滚
C: 一致性,事务必须使数据库从一个一致性状态转换成另一个一致性状态,即事务执行前后均能够保证数据库一致性
I: 隔离性,多个事务之间相互隔离
D: 持久性,对数据库中的数据改变是永久性的,即使在数据库系统故障时,也不会丢失提交事务的操作
BASE 理论
关于 AP 系统
核心思想
-
基本可用:如果出现不可预估的故障,依然保持系统可用,相比于正常系统可能会有:响应时间的损失或功能的损失
-
软状态:允许数据存在中间状态
-
最终一致性:保证系统没有其他的更新操作的情况下,数据最终能够达到一致的状态
分布式事务
二阶段提交
问题:
-
性能问题
-
协调者单点故障问题
-
网络分区带来的数据不一致
解决:
-
程序方面,使用分布式锁
-
出现问题,回滚
三阶段提交
对比“两阶段提交”
将两阶段提交中的 Prepare 阶段拆分成了两个部分:
-
CanCommit
-
PreCommit
解决了两个问题:
-
单点故障问题
-
阻塞问题
但是依然没有解决性能问题和网络分区场景带来的数据一致性问题
MVCC
先了解 “锁”
-
悲观锁:操作数据时把数据锁上,直到操作完成后才会释放;上锁期间不允许其他事务修改
-
乐观锁:不会上锁,只在执行更新时判断其他事务是否有修改数据,只有冲突时才放弃操作
MVCC 的概念
MVCC 是一种并发控制的方法,维持一个数据的多个版本,使得读写操作没有冲突。MVCC为每个修改保存一个版本,和事务的时间戳相关联。可以提高并发性能,同时解决脏读问题
时间戳问题
MVCC 的核心就是不同的时间戳,所以保证时间戳的正确性非常重要
TrueTime API
通过卫星提供一个物理时钟,最终保证时钟误差在 1~7ms 内
问题:
- 需要支付 API 费用(对于企业而言不贵
TSO 时间戳预言机
采用中心化的授时方式,所有协调者向中心化节点获取时钟
问题:
- 增加了网络通信的成本(需要考虑低延迟、高性能和容错性的问题
共识协议
Quorum NWR
三要素
-
N:在分布式存储系统中,有多少备份数据
-
W:代表一次成功的更新操作要求至少有w份数据写入成功
-
R:代表一次成功从的读取数据操作要求至少有r份数据读取成功
为了保证强一致性,需要保证 W + R > N
注意这个是必要条件,而不是充分条件
- 原因:允许数据被覆盖
RAFT 协议
这是一种分布式一致性算法(共识协议),即使出现部分节点故障、网络延迟等情况,也不影响各节点,进而提高系统的整体可用性
三角色
Leader
-
负责处理所有的客户端请求
-
向 Follower 同步请求日志,当日志同步到大多数节点上后,通知 Follower 提交日志
Follower
-
不会发生任何请求
-
接受并持久化 Leader 同步的日志,在 Leader 告知日志可以提交后,提交日志
-
当 Leader 出现故障时,主动推荐自己为 Candidate
Candidate
-
Leader 选举中的临时角色
-
向其他节点发送请求投票信息,如果获得大多数选票,晋升为 Leader
Log:节点之间同步的信息,以只追加写的方式进行同步,解决了数据被覆盖的问题
Term:单调递增,每个Term内最多只有一个 Leader
Committed:日志被复制到多数派节点,即可认为已经被提交
Applied:日志被应用到本地状态机 -> 执行了 log 中的命令,修改了内存状态
运作机制
Leader 选举
规则
-
在一个任期内每个参与者最多投一票(持久化)
-
要成为 Leader,必须拿到多数投票
流程
-
初始全部为 Follower
-
Current Term + 1
-
选举自己
-
向其他参与者发起 RequestVote,retry直到:
-
收到多数派请求,成为 Leader,并发送心跳
-
收到其他 Leader 的请求,转为 Follower,更新自己的 Term
-
收到部分,但未达到多数派,请求超时,随机 timeout 开始下一轮
-
Log Replication
新的 Leader 产生,Leader 和 Follower 不同步,Leader 强制覆盖 Followers 的不同步日志
过程
-
Leader 收到写请求 w
-
将 w 写入本地 log
-
向其他 Follower 发起 AppendEntries RPC
-
等待多数派回复
-
更新本地状态机,返回给客户端
-
下一个心跳通知 Follower 上一个 Log 已经被 Committed 了
-
Follower 也根据命令应用本地状态机
-
-
Follower 有问题,Leader 一直 Retry
切主
当 Leader 出现问题时,需要重新选举
-
Leader 发现失去 Follower 的响应,失去 Leader 身份
-
两个 Follower 之前一段时间未收到心跳,重新进行选举,选出新的 Leader,此时发生了切主
-
Leader 自杀重启,以 Follower 的身份加入进来
Stale 读
发生 Leader 切换,old leader 收到了读请求
解决:保证读的强一致
读操作在 lease timeout 内,默认自己是 leader;不是在发起一次 heartbeat,等待 Commit Index 应用到状态机
Election timeout > lease timeout:新 leader 上任,自从上次心跳之后一定超过了 Election timeout,就 leader 大概率能够发现自己的 Lease 过期
Paxos 协议
与 RAFT 算法区别:
-
Paxos 可以并发修改日志,而 Raft 写日志操作必须是连续的
-
Paxos 可以随机选主,不必最新最全的节点当选 Leader
优势:
- 写入高并发性能高,所有节点都能写入
劣势:
-
没有一个节点有完整的最新写入数据
-
恢复流程复杂,需要同步历史记录
流程
一点自己的想法
- 之前自己做 Demo 的时候根本就不会去考虑分布式会导致的问题,在上这节课之前,我对于分布式的了解只是但闻其名的程度,网上的讨论也不过是“对比单机就是用分布式锁的区别”
- 但是真正去了解这些协议才知道这里面的奥妙