分布式系统定义
定义:分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通知和协调的系统
常见问题:
- 通信异常:网络的不可靠性导致系统无法顺利进行同行。
- 网络分区:分布式系统中部分节点之间的网络延迟增大,最终导致组成分布式系统中只有部分节点能够进行正常通信,另外一些节点则不能,这种情况称之为网络分区,俗称“脑裂”
- 三态:请求和响应存在特有的是“三态”概念,即成功、失败和超时
- 节点故障:组成分布式系统服务的节点出现宕机或“僵死"现象。
一致性概念:
分布式系统对于数据复制需求,一般来源于以下两个原因:
- 为了增加系统的可用性,防止单点故障引起的系统不可用
- 提高系统的性能
一致性级别: - 强一致性
- 弱一致性:系统在写入成功后,不承诺立即可以读取写入的值,也不承诺多久之后数据能够达成一致,但会尽可能保证到某个时间级别后,数据能够达到一致状态。
- 最终一致性:是弱一致性的特例,系统会保证在一定时间内,能够达到数据一致的状态。
分布式事务-CAP
一个分布式系统不可能同时满足一致性C(Consistency)、可用性(A:Availability)和分区容错性(Partion tolerance)
C:数据在多个副本之间能够保持一致的特性
A:可用性,系统提供的服务必须一直处于可用的状态,每次请求都能获取到非常不错的响应--但不饿能保证数据是最新的。
P:分区容错性,分布式系统在遇到任何网络分区故障时,仍然能对外提供满足一致性和可用性服务,除非整个网络环境都发生了故障
分布式系统网络分区容错性是一个基本的要求,因此,系统架构师需要在C和A之间进行取舍。
分布式事务-BASE
BASE:全称Basically Available(基本可用),Soft state(软状态),Eventually consistency(最终一致)
Base理论是在CAP中一致性和可用性权衡的结果,是基于CAP定理逐步演化而来。
核心思想:应用根据自身特点,采用适当的方式来使得系统达到最终一致
Basically Avaliable
分布式系统在出现不可预知的故障时,允许损失部分可用性
响应时间上的损失:延长响应时间
功能上的损失:为了保护系统的稳定性(或者保证一致性),部分消费者可能会被引导到一个降级页面。
Soft state(软状态)
要求多个节点的数据副本都是一致的,这是一种“硬状态”
软状态:允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同的节点的数据副本之间进行数据同步的过程中存在延迟。
Eventually consistency
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步之后,最终能够达到一个一致的状态。
- 因果一致性(causal consistency):A在更新完某个数据之后通知节点B,那么节点B之后对该数据的访问和修改都是基于A更新后的值,与A无因果关系的节点C访问则没有这样的限制。
- 读己之所写(read your writes):总是访问到自身更新过的新值,而不会看到旧值。可以看成是一种特殊的因果一致性
- 会话一致性(Session consistency):执行更新过程中,客户端能够在同一个会话中始终读取到该数据项的最新值。
- 单调读一致性(monotonic read C):一个节点从系统中读取出一个数据项的值后,那么系统对于该节点后续的任何数据访问都不应该返回更旧的值。
- 单调写一致性:(write):一个系统能够保证来自同一个节点的写操作被顺序的执行。
分布式理论-2PC
什么是2PC:即两段提交协议,目前大部分关系型数据库都是采用两段式提交协议完成分布式的事务处理。
每个机器节点虽然可以保证自身的事务操作中的结果成功或失败,但是无法获取其他机器的操作结果。为了保证事务的ACID,就需要引入协调者的组件来统一调度所有分布式节点的执行逻辑。
2PC阶段一:提交事务请求
2PC阶段一:提交事务请求:
- 事务询问:协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
- 执行事务:各参与者节点执行事务操作,并将Undo(保证事务的一致性)和redo(事务的原子性和持久性)信息计入事务日志中
- 各参与者向协调者反馈事务询问的响应
如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可执行;如果参与者没有成功执行事务,就返回No个协调者,表示事务不可执行
2PC阶段二:执行事务提交
包含两种操作可能:提交事务、中断事务
提交事务步骤如下:
- 发送提交请求:协调者想所有参与制发出commit请求。
- 事务提交:参与者收到commit请求后,会正式执行提交操作,并在完成提交之后释放整个事务执行期间占用的事务资源。
- 反馈事务提交结果:参与者在完成事务提交之后,向协调者发送Ack信息
- 完成事务:协调者接收到所有参与者反馈的Ack信息后,完成事务。
中断事务步骤:
- 发送回滚请求:协调者向参与者发送Rollback请求
- 事务回滚:参与者接收到Rollback请求后,会利用阶段一中记录的Undo信息来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源。
- 反馈事务回滚结果:事务参与者在完成事务回滚之后,向协调者发送Ack信息
- 中断事务:协调者接收到所有参与者反馈的Ack信息后,完成事务中断。
二阶段就做了两个事情:投票和执行
将一个事务的处理过程分为了投票额执行两个阶段,核心是对每个事务都采用先尝试后提交的处理方式,从而保证其原子性和一致性,因此也可以将二阶段提交堪称一个强一致性的算法。
2PC的优点与缺点
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,数据不一致,过于保守
分布式理论-3PC
3PC:由Can Commit、PreCommit、doCommit三个阶段组成事务处理协议,是对2PC的请求过程一分为二。
阶段一:CanCommit
- 事务询问:协调者向所有的参与者发送一个包含了事务内容的canCommit,询问是否可以执行事务提交操作。
- 各参与者向协调者反馈事务询问响应:参与者接收到来资源自协调者的包含了事务的canCommit请求后,正常情况下,如果自身认为可以顺利执行事务,则反馈Yes响应,并进入预备状态,否则反馈No响应
阶段二:PreCommit
- 执行事务预提交
- 发送预提交请求:协调者向参与者节点发出preCommit请求,并进入prepared阶段。
- 事务预提交:参与者接收到preCommit请求后,会执行事务操作,并将Undo和Redo记录到事务日志表中。
- 各参与者向协调者反馈事务执行结果:
- 参与者执行了事务操作,那么反馈Ack,同时等待最终的指令:提交(commit)或终止(abort)
若任意一个参与者反馈了No响应,或者等待超时后,协调者无法接收到所有参与者的发明亏,则中断事务。
- 中断请求:
- 发送中断请求:协调者向所有参与者发送abort请求
- 中断事务:无论是收到来自协调者abort或者请求过程中超时,参与者都会中断事务
阶段三:doCommit
- 执行事务提交
- 发送提交请求:假设协调者处于正常工作状态,并且接收到了来自于所有参与者的Ack响应,那么他将从预提交状态转换为提交状态,并向所有的参与者发送doCommit请求。
- 事务提交:参与者接收到doCommit请求后,会正式执行事务提交操作,并在完成提交之后释放整个事务执行顾聪衡中占用的事务资源。
- 反馈事务提交结果:参与者完成事务提交之后,向协调者发送Ack响应。
- 完成事务:协调者接收到所有参与者反馈的Ack消息后,完成事务
- 中断事务
- 发送中断请求:发送abort请求
- 事务回滚:参与者根据记录的Undo信息来执行事务回滚,并在完成回滚之后释放整个事务执行期间占用的资源。
- 反馈事务回滚结果
- 中断事务:
注意:一旦进入阶段三,可能会出现两种故障
- 协调者出现问题
- 协调者和参与者之间的网络故障。
参与者在无法收到doCommit请求或者abort请求,针对这种情况,参与者都会在等待超时之后,继续执行事务提交。
3PC优缺点:
相比较2PC,最大的优点是降低了参与者的阻塞范围(第一阶段是不阻塞的),其次能够在单点故障后继续达成一致性(2PC在提交阶段出现此问题,二3PC会根据协调者的状态进行回滚或者提交)
缺点:
如果参与者收到preCommit消息后,出现了网络分区,此时协调者所在的节点和参与者所在的节点无法进行正常的网络通信,那么参与者等待超时后,会进行事务提交,这必然会出现分布式数据不一致的问题。
分布式理论:Paxos一致性算法
概念:
paxos是一种基于消息传递且具有高度容错性的一致性算法,是目前公认的解决分布式一致性问题最有小的算法之一。
Paxos解决了什么问题
答:解决了一致性问题;Paxos算法解决了如何在一个分布式系统中出现错误,快速且正确地在集群内布对某个数据的值达成一致,并且保证不论发生任何异常,都不会破坏整个系统的一致性。
Paxos相关概念
提案(Proposal)。最终要达成一致的value就在提案里。
提案Proposal:Proposal信息包括了提案编号和提议的值。
三种角色:
- Proposer:提案发起者
- Acceptor:决策者,可以批准提案
- Learner:最终决策的学习者
一个进程可能同时充当多种角色,比如一个进程可能是Proposer又是Acceptor又是Learner
【对某个数据的值达成一致】,指的是Proposer、Acceptor、Learner都认为同一个value被选定(Chosen)
- ProposerL只要Proposer发的提案被Acceptor接受,(刚开始一个Acceptor同意即可,后来需要半数以上的Acceptor同意才行),Proposer就认为该提案里的value被选定了
- Acceptor:只要Acceptor接受了某个提案,Acceptor就认为该提案里的value被选定了
- Learner:Acceptor告诉Learner哪个Value被选定了,Learner就认为value被选定了
算法优化:
如果Acceptor收到了一个编号为n的Prepare请求,在此之前它已经响应了编号大于N的Prepare请求。根据p1a,该Acceptor不可能接受编号为N的提案,因此,该Acceptor可以忽略编号为N的Prepare请求。
算法描述
阶段一:
- Proposer选择了一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求
- 如果一个Acceptor收到了一个编号为N的Prepare请求,且大于该Acceptor已经响应过反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案
阶段二:
- 如果Proposer收到半数以上的Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对(N,V)提案的Accept请求给半数以上的Acceptor。注意:V就是收到的响应中编号最大的提案的Value,如果响应不包含任何提案,那么V就由Proposer自己决定
- 如果Acceptor收到了一个正对编号为N的提案的Accept请求,只要该Accept没有对编号大于N的Prepare请求做出响应,它就应该接受该提案。
实际运行过程中,每一个Proposer都可能产生多个提案,但只要每个Proposer都遵循上述的算法运行,就一定
能够保证算法执行的正确性。
Learner学习被选定的value --参照集群中的Observer
方案一:
Learner获取一个已经被选定的提案的前提,是该提案已经被半数以上的Acceptor批准,因此,最简单的做法就是一旦Acceptor批准了一个提案,就应该将提案发送给所有的Learner;
但是需要让每个Acceptor与所有的Learner逐个进行一次通信,通信的次数至少为二者个数的乘积。
方案二:
让所有的Acceptor将他们对提案的批准情况,统一发送一个特定的Learner,各个learner之间可以通过消息通信来互相感知提案的选定情况,前提是主Learner被通知一个提案已经被选定时,他会负责通知其他的Learner
优点:通信次数减少为M+N-1
缺点:单点问题(主learner可能出现问题)
方案三:
Acceptor接受一个提案,就将该提案发送给一个learner集合,learner结合再通知其他learner
优点:结合中的learner个数越多,可靠性越好
缺点:网络通信复杂度高
如何保证Paxos算法的活性
活性:最终一定会发生的事情–最终一定要选定value
通过选取主Proposer保证算法的活性:
假设两个Proposer依次提出编号递增的提案,最终会陷入死循环,没有value被选定?
解决:通过选取主Proposer,并规定只有主Proposer才能提出议案,这样一来只要主Proposer和过半的Acceptor能够正常进行网络通信,那么单反主Proposer提出一个编号更高的提案,该提案终将会被批准,这样通过选择一个Proposer,整套Paxos算法就能保证活性。
分布式理论:一致性算法Raft
什么时Raft算法
Raft是一种为了管理复制日志的一致性算法。
领导人选举
Raft通过选举一个领导人,然后给予它全部的管理复制日志的责任来实现一致性。
服务器扮演下面的角色之一:
- 领导者:处理客户端交互,日志复制等动作,一般一次只有一个领导者
- 候选者:候选者就是再选举过程中提名自己的实体,一旦选举成功,则称为领导者
- 跟随着:类似选民,完全被动的角色,这样的服务器等待被通知投票。
选举:
Raft使用心跳机制来触发选举。当server启动时,初始状态都是follower,每个server都有一个定时器,超时时间为election timeout(一般150-300ms),如果某server没有超时的情况下收到了来自领导者或者候选者任何消息,定时器重启,如果超时,他就开始一次选举。
开始一次选举过程,跟随者先要增加自己的当前任期号并且转换到候选人状态,然后请求其他服务器为自己投票。那么会产生3种结果:
自己当选成功;
其他服务器称为领导者
僵住,没有任何人称为领导者
注意:
每一个server最多再一个任期内投出一张选票,先到先得
要求最多只能有一个人赢得选票
一旦成功,立即称为领导人,然后广播所有服务器停止投票阻止新的领导产生。
Raft通过使用随机选举超时时间的方法将服务器打散投票,每个候选人在僵住的时候会随机从一个时间开始重新选举。
日志复制(保证数据一致性)
日志复制过程:
步骤:
- 客户端的每一个请求都包含被复制状态机执行的指令
- leader把这个指令作为一条新的日志条目添加到日志中,然后并行发起RPC给其他服务器,让他们复制这条消息
- 跟随着响应ACK,如果follower当即或者运行缓慢或者丢包,leader会不断地重试,知道所有follower最终都复制了所有的日志条目
- 通知所拥有的follower提交日志,同时领导人提交这条日志到自己的状态机中,并返回给客户端