分布式事务与一致性算法
传统数据库事务:ACID, 老的方式分布式数据库:2PC、3PC 一致性算法:分布式CAP、BASE模型、柔性事务(补偿事务(TCC)(TCC编程(Try、Confirm、Cancel))) 分布式事务解决方案,包括强一致性的两阶段提交协议,三阶段提交协议,以及最终一致性的可靠事件模式、补偿模式,阿里的 TCC 模式。
刚性事务:XA分布式协议:2PC、3PC、 柔性事务:BASE模型、TCC、
分布式系统算法:Paxos、Raft、ZAB 两军问题与拜占庭将军问题
2PC/3PC用于保证多个数据分片上事务的原子性 Paxos协议用于保证同一个数据分片在多个副本的一致性
Paxos(分布式一致性算法):Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。 由proposer/acceptor/learner组成 Basic Paxos:提案阶段 投票阶段, 对一个值达成一致 Multi Paxos:统一由leader发起提议,可节省prepare步骤,连续多个paxos instance来对多个值达成一致
Raft 算法:Leader、Follower、Candidate候选人 选举流程:Candidate候选人向所有的服务器邀请投票给自己,如果收到大多数的Server的同意,就当选为Leader,其他的Server为Follower,如果一轮没有选出,则在一定的timeout后重新发起投票,直到选出Leader 使用流程:Leader 节点接收到的数据处于未提交状态(Uncommitted),接着 Leader 节点会并发向所有 Follower 节点复制数据并等待接收响应,然后再向所有 Follower 发出提交通知
Raft:拉票类型的,由Leader-->Follower ZAB:投票类型的,由Leader<--Follower
ZAB 协议 ( Zookeeper Atomic Broadcast) 原子广播协议:保证了发给各副本的消息顺序相同 两种角色+一种角色:Leader和Follower两个角色 + Observer 三种状态:Looking、Following、Leading 选举流程:初始化时候,故障恢复时候(选举和同步数据)、正常广播时候
传统事务:ACID 老的方式实现分布式事务是通过两阶段提交来实现的:2PC、3PC、 在分布式领域基于CAP理论以及BASE理论,有人就提出了 柔性事务 的概念
柔性事务(遵循BASE理论)是指相对于ACID刚性事务而言的。 支付宝所说的柔性事务分为:两阶段型、补偿型、异步确保型、最大努力通知型几种。 1、两阶段型:就是分布式事务两阶段提交,对应技术上的XA、JTA/JTS。这是分布式环境下事务处理的典型模式。 2、补偿型:TCC型事务(Try/Confirm/Cancel)可以归为补偿型。 3、异步确保型,将一些同步阻塞的事务操作变为异步的操作,避免对数据库事务的争用,典型例子是热点账户异步记账、批量记账的处理。 4、最大努力型,PPT中提到的例子交易的消息通知(例如商户交易结果通知重试、补单重试)
柔性事务针对分布式事务的解决方法: 1、记录日志+补偿 记录事务的开始和结束状态。事务根据日志记录找回事务的当前执行状态,并根据状态决定重试异常步骤,也就是正向补偿,或者回滚上一次执行步骤,也就是反向补偿。 2、消息 多次重试,也就是发送多次消息,由于要多次重发,所以程序必须是幂等(同一操作反复执行多次结果不变),这是非常具有互联网特征的一种模式。 3、“无锁”设计 放弃锁是一个解决问题的思路。比如通过乐观锁,大多数是基于版本号来实现。
https://github.com/dotnetcore/CAP
1、分布式领域CAP理论, Consistency(一致性), 数据一致更新,所有数据变动都是同步的 Availability(可用性), 好的响应性能 Partition tolerance(分区容忍性) 可靠性
数据一致性(consistency):如果系统对一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据,对调用者而言数据具有强一致性(strong consistency) (又叫原子性 atomic、线性一致性 linearizable consistency) 服务可用性(availability):所有读写请求在一定时间内得到响应,可终止、不会一直等待 分区容错性(partition-tolerance):在网络分区的情况下,被分隔的节点仍能正常对外服务
CAP定理是由加州大学伯克利分校Eric Brewer教授提出来的,他指出WEB服务无法同时满足一下3个属性: 一致性(Consistency) : 客户端知道一系列的操作都会同时发生(生效) 可用性(Availability) : 每个操作都必须以可预期的响应结束 分区容错性(Partition tolerance) : 即使出现单个组件无法可用,操作依然可以完成
C、A、P三者最多只能满足其中两个,和FLP定理一样,CAP定理也指示了一个不可达的结果(impossibility result)。 定理:任何分布式系统只可同时满足二点,没法三者兼顾。 忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。
2、关系数据库的ACID模型拥有 高一致性 + 可用性 很难进行分区: Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。 Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。 Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。 Durability. 一旦事务完成,就不能返回。
3、BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性: Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库) Soft state软状态 状态可以有一段时间不同步,异步。 Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。
这个时候有同学可能会把数据库的2PC(两阶段提交)搬出来说话了。OK,我们就来看一下数据库的两阶段提交。 对数据库分布式事务有了解的同学一定知道数据库支持的2PC,又叫做 XA Transactions。 MySQL从5.5版本开始支持,SQL Server 2005 开始支持,Oracle 7 开始支持。 其中,XA 是一个两阶段提交协议,该协议分为以下两个阶段: 第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交. 第二阶段:事务协调器要求每个数据库提交数据。
一致性模型 强一致 弱一致性 最终一致性(一段时间达到一致性)
XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。 X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 是X/Open 这个组织定义的一套分布式事务的标准,也就是了定义了规范和API接口,由这个厂商进行具体的实现。这个思想在java 平台里面到处都是。 XA规范: 应用程序( AP )、事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM ) Application Transcation Manage Rosource Manage Communication Resource Manage
常见的事务管理器( TM )是交易中间件 常见的资源管理器( RM )是数据库 常见的通信资源管理器( CRM )是消息中间件
https://www.jianshu.com/p/ab1a1c6b08a1 柔性事务针对分布式事务的解决方法: 1、记录日志+补偿 记录事务的开始和结束状态。事务根据日志记录找回事务的当前执行状态,并根据状态决定重试异常步骤,也就是正向补偿,或者回滚上一次执行步骤,也就是反向补偿。 2、消息 多次重试,也就是发送多次消息,由于要多次重发,所以程序必须是幂等(同一操作反复执行多次结果不变),这是非常具有互联网特征的一种模式。 3、“无锁”设计 放弃锁是一个解决问题的思路。比如通过乐观锁,大多数是基于版本号来实现。
https://blog.csdn.net/cxzhq2002/article/details/46892211 https://www.zhihu.com/question/31813039 柔性事务(遵循BASE理论)是指相对于ACID刚性事务而言的。 支付宝所说的柔性事务分为:两阶段型、补偿型、异步确保型、最大努力通知型几种。
1、两阶段型:就是分布式事务两阶段提交,对应技术上的XA、JTA/JTS。 这是分布式环境下事务处理的典型模式。
2、补偿型: TCC型事务(Try/Confirm/Cancel)可以归为补偿型。
3、异步确保型 将一些同步阻塞的事务操作变为异步的操作,避免对数据库事务的争用,典型例子是热点账户异步记账、批量记账的处理。
4、最大努力型 PPT中提到的例子交易的消息通知(例如商户交易结果通知重试、补单重试)
1、2PC和3PC 二阶段提交其实就是实现XA分布式事务的关键(确切地说:两阶段提交主要保证了分布式事务的原子性:即所有结点要么全做要么全不做) 跨数据库两段提交事务:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的,JavaEE中的JTA事务可以支持2PC。因为2PC是反模式,尽量不要使用2PC,使用BASE来回避。
3PC (three phase commit) 与两阶段提交不同的是,三阶段提交有两个改动点。 1、引入超时机制。同时在协调者和参与者中都引入超时机制。 2、在第一阶段分为询问阶段,具体操作两个阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。最后提交阶段如果RM超时未收到TM的commit请求,就默认提交(根据概率来的,正常应该是commit的) 也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。 因为有了准备提交(prepare to commit)阶段,3PC的事务处理延时也增加了1个RTT,变为3个RTT(propose+precommit+commit),但是它防止participant宕机后整个系统进入阻塞态,增强了系统的可用性,对一些现实业务场景是非常值得的。
TCC编程模式 所谓的TCC编程模式,也是两阶段提交的一个变种。TCC提供了一个编程框架,将整个业务逻辑分为三块:Try、Confirm和Cancel三个操作。以在线下单为例,Try阶段会去扣库存,Confirm阶段则是去更新订单状态,如果更新订单失败,则进入Cancel阶段,会去恢复库存。总之,TCC就是通过代码人为实现了两阶段提交,不同的业务场景所写的代码都不一样,复杂度也不一样,因此,这种模式并不能很好地被复用。
补偿事务(TCC) TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段: Try 阶段主要是对业务系统做检测及资源预留 Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。 Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
2、Paxos(分布式一致性算法) Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。 Paxos协议用于解决多个副本之间的一致性问题。 2PC/3PC用于保证多个数据分片上事务的原子性,Paxos协议用于保证同一个数据分片在多个副本的一致性 由proposer/acceptor/learner组成
Paxos算法描述:经过上面的推导,我们总结下Paxos算法的流程。 提案询问阶段(Prepare阶段):如果提案版本号N大于该Acceptor已经响应过的所有Prepare请求的编号,就接收,并承诺不再接收比N小的提案(prepare步骤+acceptor的promise) 提案投票阶段:发送一个针对[N,V]提案,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案
Paxos算法分为两个阶段。具体如下: 阶段一:提案阶段 (a) Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求。 (b) 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。
阶段二:投票阶段 (a) 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定。 (b) 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案。
Basic Paxos:上面理论 Multi Paxos:proposer leader在Multi Paxos中还有助于提升性能,常态下统一由leader发起提议,可节省prepare步骤(leader不用问询acceptor曾接受过的ID最大的提议、只有leader提议也不需要acceptor进行promise)直至发生leader宕机、重新选主。
Paxos是对一个值达成一致,Multi-Paxos是连续多个paxos instance来对多个值达成一致,这里最核心的原因是multi-paxos协议中有一个Leader。Leader是系统中唯一的Proposal,在lease租约周期内所有提案都有相同的ProposalId,可以跳过prepare阶段,议案只有accept过程,一个ProposalId可以对应多个Value,所以称为Multi-Paxos。
Paxos协议数据同步方式相对于基于传统1主N备的同步方式有啥区别? 一般情况下,传统数据库的高可用都是基于主备来实现,1主1备2个副本,主库crash后,通过HA工具来进行切换,提升备库为主库。在强一致场景下,复制可以开启强同步,Oracle和Mysql都是类似的复制模式。但是如果备库网络抖动,或者crash,都会导致日志同步失败,服务不可用。为此,可以引入1主N备的多副本形式,我们对比都是3副本的情况,一个是基于传统的1主2备,另一种基于paxos的1主2备。传统的1主两备,进行日志同步时,只要有一个副本接收到日志并就持久化成功,就可以返回,在一定程度上解决了网络抖动和备库crash问题。但如果主库出问题后,还是要借助于HA工具来进行切换,那么HA切换工具的可用性如何来保证又成为一个问题。基于Paxos的多副本同步其实是在1主N备的基础上引入了一致性协议,这样整个系统的可用性完全有3个副本控制,不需要额外的HA工具。而实际上,很多系统为了保证多节点HA工具获取主备信息的一致性,采用了zookeeper等第三方接口来实现分布式锁,其实本质也是基于Paxos来实现的。
3、Raft 算法也是一种少数服从多数的算法(脑裂问题也是可以解决的) 一致性算法:最初的状态都是Follower,任意一个Server都可以申请成为Candidate并申请所有的Server投票给自己,如果收到大多数的Server的同意,就当选为Leader,其他的Server为Follower,如果一轮没有选出,则在一定的timeout后重新发起投票,直到选出Leader Leader挂掉后,集群重新选主,老的Leader恢复后自动成为Follower 当因为网络原因发生脑裂,拥有大多数的一方重新选主,Client发过来的请求都可以成功,少数派的一方接收到的Client请求都是失败的,重新加入后少数派的Server自动成为Follower
Raft 协议强依赖 Leader 节点的可用性来确保集群数据的一致性。数据的流向只能从 Leader 节点向 Follower 节点转移。当 Client 向集群 Leader 节点提交数据后,Leader 节点接收到的数据处于未提交状态(Uncommitted),接着 Leader 节点会并发向所有 Follower 节点复制数据并等待接收响应,确保至少集群中超过半数节点已接收到数据后再向 Client 确认数据已接收。一旦向 Client 发出数据接收 Ack 响应后,表明此时数据状态进入已提交(Committed),Leader 节点再向 Follower 节点发通知告知该数据状态已提交。
在任何时候一个服务器可以扮演以下角色之一: Leader:负责 Client 交互 和 log 复制,同一时刻系统中最多存在一个,处理所有客户端交互,日志复制等,一般一次只有一个Leader. Follower:被动响应请求 RPC,从不主动发起请求 RPC, 类似选民,完全被动 Candidate候选人 : 由Follower 向Leader转换的中间状态,类似Proposer律师,可以被选为一个新的领导人。
Raft:拉票类型的,由Leader-->Follower ZAB:投票类型的,由Leader<--Follower
4、ZAB 协议 ( Zookeeper Atomic Broadcast) 原子广播协议:保证了发给各副本的消息顺序相同 两种角色+一种角色:Leader和Follower两个角色 + Observer 三种状态:Looking、Following、Leading ZAB 中的节点有三种状态 following:当前节点是跟随者,服从 leader 节点的命令 leading:当前节点是 leader,负责协调事务 election/looking:节点处于选举状态
阶段 ZAB协议定义了 选举(election)、发现(discovery)、同步(sync)、广播(Broadcast) 四个阶段
选举(Election) election阶段必须确保选出的Leader具有highestZXID,否则在Recovery阶段没法保证数据的一致性,Recovery阶段Leader要求Follower向自己同步数据没有Follower要求Leader保持数据同步,所有选举出来的Leader要具有最新的ZXID; 在选举的过程中会对每个Follower节点的ZXID进行对比只有highestZXID的Follower才可能当选Leader;
恢复(Recovery) :数据同步 在election阶段选举出来的Leader已经具有最新的ZXID,所有本阶段的主要工作是根据Leader的事务日志对Follower节点数据进行更新; 数据更新:复制,回滚
广播(Broadcast):类似2PC提交,只是2PC是接收全部的参与者同意,ZAB只需要超半数同意即可 客户端提交事务请求时Leader节点为每一个请求生成一个事务Proposal,将其发送给集群中所有的Follower节点,收到过半Follower的反馈后开始对事务进行提交
协议状态 ZAB协议中存在着三种状态,每个节点都属于以下三种中的一种: Looking :系统刚启动时或者Leader崩溃后正处于选举状态 Following :Follower节点所处的状态,Follower与Leader处于数据同步阶段; Leading :Leader所处状态,当前集群中有一个Leader为主进程;
ZAB中的三种角色:Leader、Follower、Observer Leader、负责发起事务 Follower、负责读写和响应leader的提议 Observer:只负责读取服务
选举流程 https://blog.csdn.net/luonanqin/article/details/78314096 https://zhuanlan.zhihu.com/p/27335748 https://dbaplus.cn/news-141-1875-1.html
初始化时候:初始化epoch和lastzxid一样,serverid最大的作为候选leader
故障恢复时候: 故障选举: 1、每个server的epoch自增,并且将自己的新的epoch发送给其他server, 2、每个server对比自己的新的epoch和接受的epoch比较,把自己的新更新较大的那个epoch 3、依次比较epoch、zxid、serverid,哪个都是最大的就成为leader
故障同步数据: 1、leader给每个follower建立一个handler线程和一个事务队列 2、每个follower给leader发送lastzxid等信息,leader和自身的max/minzxid进行比较 3、如果lastzxid<minzxid,将数据发给follower,如果在中间,就发送lastzxid~maxzxid中间的数据,如果lastzxid>maxzxid,就删除大于maxzxid数据
正常广播时候: 1、leader发送议案给follower,超过半数的follower回复ack, 2、Leader将再次向集群内Follower广播Commit信息,Commit为将之前的Proposal提交;
Leader: Leader作为整个ZooKeeper集群的主节点,负责响应所有对ZooKeeper状态变更的请求。它会将每个状态更新请求进行排序和编号,以便保证整个集群内部消息处理的FIFO。 这里补充一下ZooKeeper的请求类型。对于exists,getData,getChildren等只读请求,收到该请求的zk服务器将会在本地处理,因为由第一讲的ZAB理论可知,每个服务器看到的名字空间内容都是一致的,无所谓在哪台机器上读取数据,因此如果ZooKeeper集群的负载是读多写少,并且读请求分布得均衡的话,效率是很高的。对于create,setData,delete等有写操作的请求,则需要统一转发给leader处理,leader需要决定编号、执行操作,这个过程称为一个事务(transaction)。
Follower Follower的逻辑就比较简单了。除了响应本服务器上的读请求外,follower还要处理leader的提议,并在leader提交该提议时在本地也进行提交。Follower处理提议的过程已经在ZAB一章中描述过了。 另外需要注意的是,leader和follower构成ZooKeeper集群的法定人数,也就是说,只有他们才参与新leader的选举、响应leader的提议。
Observer 如果ZooKeeper集群的读取负载很高,或者客户端多到跨机房,可以设置一些observer服务器,以提高读取的吞吐量。Observer和Follower比较相似,只有一些小区别:首先observer不属于法定人数,即不参加选举也不响应提议;其次是observer不需要将事务持久化到磁盘,一旦observer被重启,需要从leader重新同步整个名字空间。
ZAB(ZooKeeper Atomic Broadcast ) 全称为:原子消息广播协议;ZAB可以说是在Paxos算法基础上进行了扩展改造而来的,ZAB协议设计了支持崩溃恢复,ZooKeeper使用单一主进程Leader用于处理客户端所有事务请求,采用ZAB协议将服务器数状态以事务形式广播到所有Follower上;由于事务间可能存在着依赖关系,ZAB协议保证Leader广播的变更序列被顺序的处理,:一个状态被处理那么它所依赖的状态也已经提前被处理;ZAB协议支持的崩溃恢复可以保证在Leader进程崩溃的时候可以重新选出Leader并且保证数据的完整性;
处理过程: 在ZooKeeper中所有的事务请求都由一个主服务器也就是Leader来处理,其他服务器为Follower,Leader将客户端的事务请求转换为事务Proposal,并且将Proposal分发给集群中其他所有的Follower,然后Leader等待Follwer反馈,当有 过半数(>=N/2+1) 的Follower反馈信息后,Leader将再次向集群内Follower广播Commit信息,Commit为将之前的Proposal提交;
ZooKeeper启动时所有节点初始状态为Looking,这时集群会尝试选举出一个Leader节点,选举出的Leader节点切换为Leading状态;当节点发现集群中已经选举出Leader则该节点会切换到Following状态,然后和Leader节点保持同步;当Follower节点与Leader失去联系时Follower节点则会切换到Looking状态,开始新一轮选举;在ZooKeeper的整个生命周期中每个节点都会在Looking、Following、Leading状态间不断转换;
状态切换图 :Leader在超时时间内接收不到超半数的Follower发过来的心跳或TCP连接断开,那Leader会结束当前周期的领导,切换到Looking状态,所有Follower节点也会放弃该Leader节点切换到Looking状态,然后开始新一轮选举 选举出Leader节点后ZAB进入原子广播阶段,这时Leader为和自己同步的每个节点Follower创建一个操作序列,一个时期一个Follower只能和一个Leader保持同步,Leader节点与Follower节点使用心跳检测来感知对方的存在;当Leader节点在超时时间内收到来自Follower的心跳检测那Follower节点会一直与该节点保持连接;若超时时间内Leader没有接收到来自过半Follower节点的心跳检测或TCP连接断开,那Leader会结束当前周期的领导,切换到Looking状态,所有Follower节点也会放弃该Leader节点切换到Looking状态,然后开始新一轮选举;
ZAB 协议的核心:定义了事务请求的处理方式。 所有事务请求必须由一个全局唯一的服务器来协调处理,这样的服务器被称为 Leader服务器,而余下的其他服务器则成为 Follower 服务器。 Leader 服务器负责将一个客户端事务请求转换成一个事务proposal(提议),并将该 Proposal分发给集群中所有的Follower服务器。之后 Leader 服务器需要等待所有Follower 服务器的反馈,一旦超过半数的Follower服务器进行了正确的反馈后,那么 Leader 就会再次向所有的 Follower服务器分发Commit消息,要求其将前一个proposal进行提交。
如果让 Leader 选举算法能够保证新选举出来的 Leader 服务器拥有集群中所有机器最高编号(即 ZXID 最大)的事务 Proposal,那么就可以保证这个新选举出来的 Leader —定具有所有已经提交的提案。同时,如果让具有最高编号事务 Proposal 的机器来成为 Leader, 就可以省去 Leader 服务器检查 Proposal 的提交和丢弃工作的这一步操作。
数据同步 Leader 服务器会为每一个 Follower 服务器都准备一个队列,并将那些没有被各 Follower 服务器同步的事务以 Proposal 消息的形式逐个发送给 Follower 服务器,并在每一个 Proposal 消息后面紧接着再发送一个 Commit 消息,以表示该事务已经被提交。等到 Follower 服务器将所有其尚未同步的事务 Proposal 都从 Leader 服务器上同步过来并成功应用到本地数据库中后, Leader 服务器就会将该 Follower 服务器加入到真正的可用 Follower 列表中,并开始之后的其他流程。
下面来看 ZAB 协议是如何处理那些需要被丢弃的事务 Proposal 的。在 ZAB 协议的事务编号 ZXID 设计中, ZXID 是一个 64 位的数字,低 32 位可以看作是一个简单的单调递增的计数器,针对客户端的每一个事务请求, Leader 服务器在产生一个新的事务 Proposal 的时候,都会对该计数器进行加1操作;高 32 位代表了 Leader 周期 epoch 的编号,每当选举产生一个新的 Leader 服务器,就会从这个 Leader 服务器上取出其本地日志中最大事务 Proposal 的 ZXID ,并从该 ZXID 中解析出对应的 epoch 值,然后再对其进行加1操作,之后就会以此编号作为新的 epoch, 并将低 32 位置0来开始生成新的 ZXID 。
基于这样的策略,当一个包含了上一个 Leader 周期中尚未提交过的事务 Proposal的服务器启动加入到集群中,发现此时集群中已经存在leader,将自身以Follower 角色连接上 Leader 服务器之后, Leader 服务器会根据自己服务器上最后被提交的 Proposal来和 Follower 服务器的 Proposal进行比对,发现follower中有上一个leader周期的事务Proposal时,Leader 会要求 Follower 进行一个回退操作——回退到一个确实已经被集群中过半机器提交的最新的事务 Proposal 。
主从架构下,leader 崩溃,数据一致性怎么保证?leader 崩溃之后,集群会选出新的 leader,然后就会进入恢复阶段,新的 leader 具有所有已经提交的提议,因此它会保证让 followers 同步已提交的提议,丢弃未提交的提议(以 leader 的记录为准),这就保证了整个集群的数据一致性。 选举 leader 的时候,整个集群无法处理写请求的,如何快速进行 leader 选举?这是通过 Fast Leader Election 实现的,leader 的选举只需要超过半数的节点投票即可,这样不需要等待所有节点的选票,能够尽早选出 leader。
paxos 算法与 raft 算法的差异 raft强调是唯一leader的协议,此leader至高无上 raft:新选举出来的leader拥有全部提交的日志,而 paxos 需要额外的流程从其他节点获取已经被提交的日志,它允许日志有空洞 相同点:得到大多数的赞成,这个 entries 就会定下来,最终所有节点都会赞成
分布式事务的作用是保证跨节点事务的原子性,涉及事务的节点要么都提交(执行成功),要么都不提交(回滚)。分布式事务的一致性通常通过2PC来保证(Two-Phase Commit, 2PC),2PC的最大问题是,协调者是单点(需要有一个备用节点),另外协议是阻塞协议,任何一个参与者故障,都需要等待(可以通过加入超时机制)。 Paxos协议用于解决多个副本之间的一致性问题。 2PC用于保证多个数据分片上事务的原子性,Paxos协议用于保证同一个数据分片在多个副本的一致性,所以两者可以是互补的关系,绝不是替代关系。对于2PC协调者单点问题,可以利用Paxos协议解决,当协调者出问题时,选一个新的协调者继续提供服务。
raft协议和zab协议区别: 第一次写答案.最近正在实现raft协议, zab协议没看过,就刚才粗略地现看了下ZooKeeper Internals和论文, 所以下面的回答只是我自己的一些拙见,欢迎大牛们斧正.因为raft比zab出来晚点,可能raft 里面的有些东西会借鉴zab协议.其实两个协议差不到哪里去,本质上都是维护一个replicated log. 相同点(不全,没有实现过zab): 1、都使用timeout来重新选择leader. 2、采用quorum来确定整个系统的一致性(也就是对某一个值的认可),这个quorum一般实现是集群中半数以上的服务器,zookeeper里还提供了带权重的quorum实现. 3、都由leader来发起写操作. 4、都采用心跳检测存活性. 5、leader election都采用先到先得的投票方式. 不同点(不全,没有实现过zab): 1、zab用的是epoch和count的组合来唯一表示一个值, 而raft用的是term和index. 2、zab的follower在投票给一个leader之前必须和leader的日志达成一致,而raft的follower则简单地说是谁的term高就投票给谁. 3、raft协议的心跳是从leader到follower, 而zab协议则相反. 4、raft协议数据只有单向地从leader到follower(成为leader的条件之一就是拥有最新的log), 而zab协议在discovery阶段, 一个prospective leader需要将自己的log更新为quorum里面最新的log,然后才好在synchronization阶段将quorum里的其他机器的log都同步到一致.
BTW, raft实现起来比zab会简单很多.
CAP原理和BASE思想 http://www.jdon.com/37625 http://www.cnblogs.com/bangerlee/p/5328888.html
FLP Impossibility http://blog.csdn.net/chen77716/article/details/27963079
关于分布式事务、两阶段提交协议、三阶提交协议 http://blog.jobbole.com/95632/ https://www.cnblogs.com/binyue/p/3678390.html
分布式事务与一致性算法Paxos & raft & zab http://blog.csdn.net/followmyinclinations/article/details/52870418
raft协议和zab协议有啥区别? https://www.zhihu.com/question/28242561
Paxos算法 https://www.cnblogs.com/linbingdong/p/6253479.html https://www.cnblogs.com/cchust/p/5617989.html http://blog.csdn.net/xiaqunfeng123/article/details/51712983 https://www.cnblogs.com/bangerlee/p/5655754.html https://yq.aliyun.com/articles/156281
分布式系统的Raft算法: http://www.jdon.com/artichect/raft.html http://www.cnblogs.com/mindwind/p/5231986.html https://raft.github.io/ http://www.infoq.com/cn/articles/raft-paper
ZAB协议: http://blog.csdn.net/wangyangzhizhou/article/details/52698555 http://blog.jobbole.com/104985/ https://www.cnblogs.com/jian-xiao/p/5821675.html ZAB中的三种角色:Leader、Follower、Observer https://blog.csdn.net/mayp1/article/details/52026797
拜占庭问题与两军问题 http://blog.csdn.net/wulinjun777/article/details/59012687
2PC是指Oracle的两阶段提交协议(Two-Phase Commit protocol)。 2PC用于确保所有分布式事务能够同时提交(Commit)或者回滚(Rollback),以便使的数据库能够处于一致性状态(consistent state)。 分布式事务可以通过DBA_2PC_PENDING 和 DBA_2PC_NEIGHBORS 字典视图查看。
分布式事务处理是指一个事务可能涉及多个数据库操作 分布式事务处理的关键是必须有一种方法可以知道事务在任何地方所做的所有动作,提交或回滚事务必须产生一致的结果(全部提交或全部回滚)。
XA是X/Open DTP组织(X/Open DTP group)定义的两阶段提交协议,XA被许多数据库(如Oracle和DB2)和中间件等工具(如CICS 和 Tuxedo).本地支持 。 X/Open DTP模型(1994)包括应用程序(AP)、事务管理器(TM)、资源管理器(RM)、通信资源管理器(CRM)四部分。在这个模型中,通常事务管理器(TM)是交易中间件,资源管理器(RM)是数据库,通信资源管理器(CRM)是消息中间件。
一般情况下,某一数据库无法知道其它数据库在做什么,因此,在一个DTP环境中,交易中间件是必需的,由它通知和协调相关数据库的提交或回滚。而一个数据库只将其自己所做的操作(可恢复)影射到全局事务中。
XA就是X/Open DTP定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。XA接口函数由数据库厂商提供。通常情况下,交易中间件与数据库通过XA 接口规范,使用两阶段提交来完成一个全局事务,XA规范的基础是两阶段提交协议。
在第一阶段,交易中间件请求所有相关数据库准备提交(预提交)各自的事务分支,以确认是否所有相关数据库都可以提交各自的事务分支。当某一数据库收到预提交后,如果可以提交属于自己的事务分支,则将自己在该事务分支中所做的操作固定记录下来,并给交易中间件一个同意提交的应答,此时数据库将不能再在该事务分支中加入任何操作,但此时数据库并没有真正提交该事务,数据库对共享资源的操作还未释放(处于锁定状态)。如果由于某种原因数据库无法提交属于自己的事务分支,它将回滚自己的所有操作,释放对共享资源上的锁,并返回给交易中间件失败应答。
在第二阶段,交易中间件审查所有数据库返回的预提交结果,如所有数据库都可以提交,交易中间件将要求所有数据库做正式提交,这样该全局事务被提交。而如果有任一数据库预提交返回失败,交易中间件将要求所有其它数据库回滚其操作,这样该全局事务被回滚。
Last updated
Was this helpful?