分布式事物基本理论:基本遵循CPA理论,采用柔性事物特征,软状态或者最终一致性特色保证分布式事物一致性问题。html
分布式事物常看法决方案:数据库
2PC两段提交协议分布式
3PC三段提交协议(弥补两端提交协议缺点)性能
TCC或者GTS(阿里)优化
消息中间件最终一致性设计
使用LCN解决分布式事物,理念“LCN并不生产事务,LCN只是本地事务的搬运工”。3d
两阶段提交又称2PC,2PC是一个很是经典的强一致、中心化的原子提交协议
。日志
这里所说的中心化是指协议中有两类节点:一个是中心化协调者节点
(coordinator)和N个参与者节点
(partcipant)。code
两个阶段
:第一阶段:投票阶段 和第二阶段:提交/执行阶段。htm
举例
订单服务A,须要调用 支付服务B 去支付,支付成功则处理购物订单为待发货状态,不然就须要将购物订单处理为失败状态。
那么看2PC阶段是如何处理的
第一阶段主要分为3步
1)事务询问
协调者 向全部的 参与者 发送事务预处理请求,称之为Prepare,并开始等待各 参与者 的响应。
2)执行本地事务
各个 参与者 节点执行本地事务操做,但在执行完成后并不会真正提交数据库本地事务,而是先向 协调者 报告说:“我这边能够处理了/我这边不能处理”。.
3)各参与者向协调者反馈事务询问的响应
若是 参与者 成功执行了事务操做,那么就反馈给协调者 Yes 响应,表示事务能够执行,若是没有 参与者 成功执行事务,那么就反馈给协调者 No 响应,表示事务不能够执行。
第一阶段执行完后,会有两种可能。一、全部都返回Yes. 二、有一个或者多个返回No。
成功条件
:全部参与者都返回Yes。
第二阶段主要分为两步
1)全部的参与者反馈给协调者的信息都是Yes,那么就会执行事务提交
协调者 向 全部参与者 节点发出Commit请求.
2)事务提交
参与者 收到Commit请求以后,就会正式执行本地事务Commit操做,并在完成提交以后释放整个事务执行期间占用的事务资源。
异常条件
:任何一个 参与者 向 协调者 反馈了 No 响应,或者等待超时以后,协调者还没有收到全部参与者的反馈响应。
异常流程第二阶段也分为两步
1)发送回滚请求
协调者 向全部参与者节点发出 RoollBack 请求.
2)事务回滚
参与者 接收到RoollBack请求后,会回滚本地事务。
经过上面的演示,很容易想到2pc所带来的缺陷
1)性能问题
不管是在第一阶段的过程当中,仍是在第二阶段,全部的参与者资源和协调者资源都是被锁住的,只有当全部节点准备完毕,事务 协调者 才会通知进行全局提交,
参与者 进行本地事务提交后才会释放资源。这样的过程会比较漫长,对性能影响比较大。
2)单节点故障
因为协调者的重要性,一旦 协调者 发生故障。参与者 会一直阻塞下去。尤为在第二阶段,协调者 发生故障,那么全部的 参与者 还都处于
锁定事务资源的状态中,而没法继续完成事务操做。(虽然协调者挂掉,能够从新选举一个协调者,可是没法解决由于协调者宕机致使的参与者处于阻塞状态的问题)
2PC出现单点问题的三种状况
(1)协调者正常,参与者宕机
因为 协调者 没法收集到全部 参与者 的反馈,会陷入阻塞状况。
解决方案:引入超时机制,若是协调者在超过指定的时间尚未收到参与者的反馈,事务就失败,向全部节点发送终止事务请求。
(2)协调者宕机,参与者正常
不管处于哪一个阶段,因为协调者宕机,没法发送提交请求,全部处于执行了操做可是未提交状态的参与者都会陷入阻塞状况.
解决方案:引入协调者备份,同时协调者需记录操做日志.当检测到协调者宕机一段时间后,协调者备份取代协调者,并读取操做日志,向全部参与者询问状态。
(3)协调者和参与者都宕机
1) 发生在第一阶段: 由于第一阶段,全部参与者都没有真正执行commit,因此只需从新在剩余的参与者中从新选出一个协调者,新的协调者在从新执行第一阶段和第二阶段就能够了。
2)发生在第二阶段 而且 挂了的参与者在挂掉以前没有收到协调者的指令。也就是上面的第4步挂了,这是可能协调者尚未发送第4步就挂了。这种情形下,新的协调者从新执行第一阶段和第二阶段操做。
3)发生在第二阶段 而且 有部分参与者已经执行完commit操做。就比如这里订单服务A和支付服务B都收到协调者 发送的commit信息,开始真正执行本地事务commit,但突发状况,Acommit成功,B确挂了。这个时候目前来说数据是不一致的。虽然这个时候能够再经过手段让他和协调者通讯,再想办法把数据搞成一致的,可是,这段时间内他的数据状态已是不一致的了! 2PC 没法解决这个问题。
三阶段提交协议(3PC)主要是为了解决两阶段提交协议的阻塞问题,2pc存在的问题是当协做者崩溃时,参与者不能作出最后的选择。所以参与者可能在协做者恢复以前保持阻塞。三阶段提交(Three-phase commit),是二阶段提交(2PC)的改进版本。
与两阶段提交不一样的是,三阶段提交有两个改动点。
一、 引入超时机制。同时在协调者和参与者中都引入超时机制。 二、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段以前各参与节点的状态是一致的。
也就是说,除了引入超时机制以外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit
、PreCommit
、DoCommit
三个阶段。
以前2PC的一阶段是本地事务执行结束后,最后不Commit,等其它服务都执行结束并返回Yes,由协调者发生commit才真正执行commit。而这里的CanCommit指的是 尝试获取数据库锁 若是能够,就返回Yes。
这阶段主要分为2步
事务询问
协调者 向 参与者 发送CanCommit请求。询问是否能够执行事务提交操做。而后开始等待 参与者 的响应。
响应反馈
参与者 接到CanCommit请求以后,正常状况下,若是其自身认为能够顺利执行事务,则返回Yes响应,并进入预备状态。不然反馈No
在阶段一中,若是全部的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。这里的PreCommit阶段 跟上面的第一阶段是差很少的,只不过这里 协调者和参与者都引入了超时机制 (2PC中只有协调者能够超时,参与者没有超时机制)。
这里跟2pc的阶段二是差很少的。
总结
相比较2PC而言,3PC对于协调者(Coordinator)和参与者(Partcipant)都设置了超时时间,而2PC只有协调者才拥有超时机制。这解决了一个什么问题呢?
这个优化点,主要是避免了参与者在长时间没法与协调者节点通信(协调者挂掉了)的状况下,没法释放资源的问题,由于参与者自身拥有超时机制会在超时后,
自动进行本地commit从而进行释放资源。而这种机制也侧面下降了整个事务的阻塞时间和范围。
另外,经过CanCommit、PreCommit、DoCommit三个阶段的设计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段以前各参与节点的状态是一致的。
以上就是3PC相对于2PC的一个提升(相对缓解了2PC中的前两个问题),可是3PC依然没有彻底解决数据不一致的问题。
只要本身变优秀了,其余的事情才会跟着好起来(上将5)