分布式概述
分布式系统是计算机程序的集合,这些程序利用跨多个独立计算节点的计算资源来实现共同的目标。可以分为分布式计算,分布式存储,分布式数据库等。
优势:
- 去中心化
- 低成本
- 弹性
- 资源共享
- 可靠性高
挑战:
- 普遍的节点故障
- 不可靠的网络
- 异构的机器与环境硬件
- 安全
Why-How-What
使用者视角
Why:
- 数据爆炸,对存储和计算有大规模运用的诉求
- 成本低,构建在廉价服务器之上
How:
- 分布式框架
- 成熟的分布式系统
What:
- 理清规模,负载,一致性要求等
- 明确稳定性要求,制定技术方案
常见的分布式系统
系统模型
故障模型
根据对故障处理的难易程度进行划分
故障类型
拜占庭将军问题
一组拜占庭将军分别各率领一支军队共同围困一座城市。为了简化问题,将各支军队的行动策略限定为进攻或撤离两种。因为部分军队进攻部分军队撤离可能会造成灾难性后果,因此各位将军必须通过投票来达成一致策略,即所有军队一起进攻或所有军队一起撤离。因为各位将军分处城市不同方向,他们只能通过信使互相联系。在投票过程中每位将军都将自己投票给进攻还是撤退的信息通过信使分别通知其他所有将军,这样一来每位将军根据自己的投票和其他所有将军送来的信息就可以知道共同的投票结果而决定行动策略。
要对进攻达成共识
理论上无解
共识与消息传递不同,即使保证了消息传递成功,也不能保证达成共识。TCP三次握手是两将军问题的一个工程解。
共识和一致性问题
时间和事件顺序
Lamport逻辑时钟
理论基础
CAP理论
| 选项 | 描述 |
|---|---|
| C(Consistence) | 一致性,指数据在多个副本之间能够保持一致的特性 |
| A(Availability) | 可用性,指系统提供的服务必须一直处于可用的状态,每次请求能够获得非错的响应,但是不保证获取的数据是最新的 |
| P(Network partitioning) | 分区容错性,分布式系统在任何网络分区遭遇故障的时候,仍能够对外提供满足一致性和可用性的服务 |
ACID理论
事务是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
- 原子性,事务是一个完整的操作。事务的各元素是不可分的(原子的)。事务中的所有元素必须作为一个整体提交或回滚。如果事务中的任何元素失败,则整个事务将失败。
- 一致性,当事务完成时,数据必须处于一致状态。也就是说,在事务开始之前,数据库中存储的数据处于一致状态。在正在进行的事务中. 数据可能处于不一致的状态,如数据可能有部分被修改。然而,当事务成功完成时,数据必须再次回到已知的一致状态。通过事务对数据所做的修改不能损坏数据,或者说事务不能使数据存储处于不稳定的状态。
- 隔离性,对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务。修改数据的事务可以在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据。
- 持久性,事务的持久性指不管系统是否发生了故障,事务处理的结果都是永久的。一个事务成功完成之后,它对数据库所作的改变是永久性的,即使系统出现故障也是如此。也就是说,一旦事务被提交,事务对数据所做的任何变动都会被永久地保留在数据库中。
BASE理论
Base理论是对CAP中一致性和可用性权衡的结果,其来源于对大型互联网分布式总结的实践,是基于CAP定理逐步演化而来的。其核心思想是:
- Basically Available(基本可用):假设系统出了不可预知的故障,但是还可以使用,相比较于正常的系统,损失了响应时间或者一部分功能。
- Soft State(软状态):允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。
- Eventually consistent(最终一致性):系统能够保证在没有其他更新操作的情况下,数据最终一定能到达一致的状态。因此所有客户端对系统的数据访问最终都能获得最新的值。
分布式事务
二阶段提交
为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种算法。
三个假设:
- 引入协调者(Coordinator)和参与者(Participants),互相进行网络通信
- 所有节点都采用预写式日志,且日志被写入后即保存在可靠的存储设备
- 所有节点不会永久性损坏,即使损坏后仍然可以恢复
可能出现的情况:
- Coordinator不宕机,Participant宕机。需要进行回滚操作
- Coordinator宕机,Participant不宕机。可以起新的Coordinator,待查询状态后,重复二阶段提交
- Coordinator和Participant均宕机。无法确认状态,需要数据库管理员介入
回滚:在Prepare阶段,若某个事务参与者反馈失败消息,说明节点的本地事务执行不成功,必须会滚。
二阶段的问题
- 性能问题,两阶段需要多次的网络通信,耗时过大
- 协调者单点故障问题,如果事务协调者节点宕机,需要另起新的协调者,否则参与者处于中间状态无法完成事务
- 网络分区带来的数据不一致,一部分参与者收到了commit信息,另一部分没收到,则会导致节点数据之间的不一致
三阶段提交
与两阶段的区别: 将两阶段中的Prepare阶段,拆分成两部分:CanCommit和PreCommit机制
解决了两个问题:
- 单点故障问题
- 阻塞问题
引入了超时机制,在等待超时后,会继续进行事务提交。
三阶段没有解决:性能问题。网络分区带来的数据一致性问题。
MVCC
MVCC是一种并发控制的方法,维持一个数据的多个版本读写操作没有冲突。所以既不会阻塞写,也不会阻塞读。MVCC为每个修改保存一个版本,和事务的时间戳相关联。可以提高并发性能,解决脏读问题。
共识协议
Quorum NWR模型
三要素:
- N,在分布式存储系统中,有多少份备份数据
- W,代表一次成功的更新操作要求至少有W份数据写入成功
- R:代表一次成功的读操作要求至少有R份数据成功读取
为了保证强一致性,需要保证W+R>N
会引发更新问题
RAFT协议
Raft协议是一种分布式一致性算法(共识算法),共识就是多个节点对某一个事件达成一致的算法,即使出现部分节点故障,网络延时等情况,也不影响各节点,进而提高系统的整体可用性。Raft是使用较为广泛的分布式协议。一定意义上讲,RAFT也使用了Quorum机制。
- Leader,接受客户端请求,并向Follower同步请求日志,当日志同步到大多数节点上后高速Follower提交日志。
- Follower,接受并持久化Leader同步的日志,在Leader告知日志可以提交后,提交日志。当Leader出现故障时,主动推荐自己为候选人。
- Candidate,Leader选举过程中的临时角色。向其他节点发送请求投票信息,如果获得大多数选票,则晋升为Leader。
Raft要求系统在任意时刻最多只有一个Leader,正常工作期间只有Leader和Follower,Raft算法将时间划分为任意不同长度的任期(Term),每一任期的开始都是一次选举,一个或多个候选人会试图称为Leader,在成功选举Leader后,Leader会在整个任期内管理整个集群,如果Leader选举失败,该任期就会因为没有Leader而结束,开始下一任期,并立刻开始下一次选举。
Leader选举
Raft使用心跳机制来触发领导者选举,当服务器启动时,初始化都是Follower身份,由于没有Leader,Followers无法与Leader保持心跳,因此,Followers会认为Leader已经下线,进而转为Candidate状态,然后Candidate向集群其他节点请求投票,同意自己成为Leader,如果Candidate收到超过半数节点的投票(N/2 +1),它将获胜成为Leader。
Leader向所有Follower周期性发送heartbeat,如果Follower在选举超时时间内没有收到Leader的heartbeat,就会等待一段随机的时间后发起一次Leader选举。
切主:
当Leader出现问题,需要重新选举。
- Leader发现失去了Follower的响应,失去Leader身份
- 两个Follower之间一段时间未收到心跳,重新进行选举,选出新的Leader,发生切主
- Leader自杀重启,以Follower的身份加入进来
Stale读:
如果发生Leader切换,old Leader收到了读请求。如果直接响应,可能会有Stale Read。
解决方案:保持读的强一致性
读操作发生在lease timeout内,默认自己是leader;不是则发起一次heartbeat。等待commit index应用到状态机。
Election timeout > lease timeout:新leader上任,自从上次心跳之后一定超过了election timeout。旧leader大概率发现自己lease过期。
日志同步
Raft算法实现日志同步的具体过程如下:
Leader收到来自客户端的请求,将之封装成log entry并追加到自己的日志中;Leader并行地向系统中所有节点发送日志复制消息;- 接收到消息的节点确认消息没有问题,则将
log entry追加到自己的日志中,并向Leader返回ACK表示接收成功; Leader若在随机超时时间内收到大多数节点的ACK,则将该log entry应用到状态机并向客户端返回成功。
分布式实践
TODO