1. 分布式事务
满足ACID(原子性、一致性、隔离性、持久性)的一组操作,可以被称为一个事务。
同样的,分布式事务也部分遵循 ACID 规范:
- 原子性:严格遵循
- 一致性:事务完成后的一致性严格遵循;事务中的一致性可适当放宽
- 隔离性:并行事务间不可影响;事务中间结果可见性允许安全放宽
- 持久性:严格遵循
为了保证数据变更请求在整个分布式环境下正确地执行,不会导致部分服务器暂时崩溃导致整个集群提供的服务和数据不再相同,在整个分布式系统处理数据变更请求的过程中,需要引入分布式事务的概念。常见的提交方式有二阶段提交(Two-phase Commit,2PC)和三阶段提交(Three-phase commit,3PC)。
二阶段提交
二阶段提交的底层实现主要分成两个阶段:
- 请求阶段
- 提交阶段
请求阶段
协调者通知每个参与者准备提交;
参与者在本地执行事务:
- 执行成功后,并不提交,告知协调者自己本地已经执行成功;
- 执行失败后,告知协调者本地作业执行故障
提交阶段
协调者根据第一阶段收集到的参与者的返回信息,决定是否提交:
- 如果全部的参与者都反馈成功,那么协调者通知所有参与者提交事务
- 如果存在参与者反馈失败,则协调者通知所有参与者取消事务
收到全部参与者的成功commit信息后,完成本次提交
二阶段提交存在的问题
- 参与者阻塞
若某个参与者一直没有完成,则需要等待他完成。例如某个柜员业务不熟悉操作很慢,那么客户和经理需要一直等待他完成操作,才能一起进入下一步 - 单点故障
若协调者寄了,那么参与者长期阻塞 - 存在数据不一致情况
若协调者在第二阶段挂了,那么会产生数据不一致的情况。
三阶段提交
三阶段提交在二阶段算法的基础上进行了优化和改进。在整个三阶段提交的过程中,相比二阶段提交,增加了预提交阶段。
canCommit阶段
协调者首先询问所有的参与者的状态,当前是否可以执行业务;如果可以\不可以执行,就直接返回可以/不可以。
preCommit阶段
协调者根据参与者canCommit阶段的响应来决定是否可以继续事务的preCommit操作。preCommit阶段和二阶段提交里面的请求阶段一致
协调者通知每个参与者准备提交;
参与者在本地执行事务:
- 执行成功后,并不提交,告知协调者自己本地已经执行成功;
- 执行失败后,告知协调者本地作业执行故障
doCommit阶段
协调者根据参与者preCommit阶段的响应来决定是否可以继续事务的doCommit操作。
发送doCommit后,若接收到了所有参与者的haveCommitted响应,则执行成功;若仅接收到了部分haveCommitted响应,则事务执行中断。
特点(重要)
相比2PC,引入超时机制,减少了阻塞问题。此外,增加了一个询问阶段,询问阶段可以确保尽可能早的发现无法执行操作而需要中止的行为。
但是,仍然存在数据不一致问题,在第三阶段如果只有一个参与者收到了abort操作指令,协调者和其他的参与者都会超时,协调者和参与者都继续提交事务,默认为成功,导致数据不一致。
MVCC
- MVCC:多版本并发控制的方法。维持一个数据的多个版本使读写操作没有冲突。所以既不会阻塞写,也不阻塞读。提高并发性能的同时也解决了脏读的问题。
- 悲观锁和乐观锁
- 悲观锁:操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据
- 乐观锁:不会上锁,只是在执行更新时判断别人是否修改数据,只有冲突时才放弃操作
- 版本的选取:使用物理时钟或逻辑时钟
- 物理时钟:提供TrueTime API,有Master节点维持一个绝对时间,保证各个服务器之间时钟误差控制在ϵ内,通常ϵ<7ms。
- 逻辑时钟:中心化授时的方式–时间戳预言机(TSO),好处是无需硬件的支持
2. 共识协议(一致性协议)
Quorum NWR模型(重要)
- 三要素:
- N:在分布式存储系统中,有多少份备份数据
- W:代表一次成功的更新操作要求至少有w份数据写入成功
- R: 代表一次成功的读数据操作要求至少有R份数据成功读取
- 为了保证强一致性,需要保证 W+R>N
- Quorum NWR模型将CAP的选择交给用户,是一种简化版的一致性模型
- 引起的并发更新问题
- 如果允许数据被覆盖,则并发更新容易引起一致性问题
RAFT协议
- 概述
- Raft协议是一种分布式一致性算法(共识算法),即使出现部分节点故障,网络延时等情况,也不影响各节点,进而提高系统的整体可用性。Raft是使用较为广泛的分布式协议。
- 三种角色
- Leader - 领导者:Leader 负责处理所有的客户端请求,并向Follower同步请求日志,当日志同步到大多数节点上后,通知Follower提交日志
- Follower - 跟随者:接受并持久化Leader同步的日志,在Leader告知日志可以提交后,提交日志
- Candidate - 备选者:Leader选举过程中的临时角色。向其他节点发送请求投票信息
- 四种定义:
- Log(日志):节点之间同步的信息,以只追加写的方式进行同步,解决了数据被覆盖的问题
- Term(任期号):单调递增,每个Term内最多只有一个Leader
- Committed:日志被复制到多数派节点,即可认为已经被提交
- Applied:日志被应用到本地状态机:执行了log中命令,修改了内存状态
- 状态转移:
- Leader选举过程:
- 初始全部为Follower
- Current Term + 1
- 选举自己
- 向其它参与者发起RequestVote请求,retry直到
- 收到多数派请求,成为Leader,并发送心跳
- 收到其它Leader的请求,转为Follower,更新自己的Term
- 收到部分,但未达到多数派,选举超时,随机timeout开始下一轮
- Log Replication过程:
- 新Leader产生,Leader和Follower不同步,Leader强制覆盖Followers的不同步的日志
- 切主:当Leader出现问题时,就需要进行重新选举
- Leader发现失去Follower的响应,失去Leader身份
- 两个Follower之间一段时间未收到心跳,重新进行选举,选出新的Leader,此时发生了切主
- Leader自杀重启,以Follower的身份加入进来
- Stale读:
- 发生Leader切换,old leader收到了读请求。如果直接响应,可能会有Stale Read
Paxos协议
- Paxos算法与RAFT算法区别:
- Multi-Paxos 可以并发修改日志,而Raft写日志操作必须是连续的
- Multi-Paxos 可以随机选主,不必最新最全的节点当选Leader
- 优劣势
- 优势:写入并发性能高,所有节点都能写
- 劣势:没有一个节点有完整的最新的数据,恢复流程复杂,需要同步历史记录