大型的分布式系统架构都会涉及到事务的分布式处理的问题,基原本说,分布式事务和普通事务都有一个共同原则:数据库
另一个设计原则,分布式系统要符合如下原则:网络
因为在设计分布式系统时,难以保证CAP所有符合,最多保证其中两个,例如在一个分布式系统中:
要保证系统数据库的强一致性,须要跨表跨库占用数据库资源,在复杂度比较高的状况下,耗时难以保证,就会出现可用性没法保证的状况。架构
故而又出现了BASE理论异步
实际上BASE理论是基于AP的一个扩展,一个分布式事务不须要强一致性,只须要达到一个最终一致性就能够了。分布式
分布式事务就是处理分布式中各个节点的数据操做,使之可以在节点相互隔离的状况下完成多个节点数据的一致性操做。性能
2PC即二阶段提交,在这里须要了解两个概念spa
准备阶段中,协调者向参与者发送precommit的消息,参与者在本地执行事务逻辑,若是没有超时以及运行无误,那么会记录redo和undo日志,将ack信息发送给协调者,当协调者收到全部节点参与者发送的ack信息时,准备进入下一阶段,不然会发送回滚信息给各个节点,各个节点根据以前记录好的undo信息回滚,本次事务提交失败。设计
提交阶段中,协调者已经收到全部节点的应答信息,接下来发送commit消息给各个节点,通知各个节点参与者能够提交事务,各个参与者提交完毕后一一发送完成信息给协调者,并释放本地占用的资源,协调者收到全部完成消息后,完成事务。日志
二阶段提交的图示以下:中间件
二阶段提交虽然可以解决大多数的分布式事务的问题,且发生数据错误的几率极小,但仍然有如下几个问题:
针对于以上提出的一些问题,衍生出了3PC。
3PC即三阶段提交协议。
3PC相对于2PC,有了如下变化:
这是一个准备阶段,在这一阶段中,协调者向参与者发送CanCommit消息,参与者接收后,根据自身资源状况判断是否能够执行事务操做,若是能够而且未超时,则发送yes给协调者,反之,协调者会中断事务。
这是预备阶段,在这一阶段中,协调者向参与者发送PreCommit消息,参与者接收后,会执行事务操做,记录undo和redo日志,事务执行完毕后会将Ack消息发送给协调者,协调者在未超时的状况下收集全部参与者的信息,不然中断事务,通知全部参与者Abort消息。
当全部参与者Ack消息完毕以后,协调者会确认发送DoCommit消息给每个参与者,执行提交事务。原则上全部参与者执行提交完毕以后,须要发送Committed给协调者,协调者完成事务。不然协调者中断事务,参与者接收abort消息会根据以前记录的undo回滚。
但也要注意,此阶段中若是参与者没法及时收到协调者发来的Docommit消息时,也会自行提交事务,由于从几率上来说,PreCommit这个阶段可以不被abort说明所有节点均可以正常执行事务提交,因此通常来说单个节点提交不影响数据一致性,除非极端状况。
相对于2PC,3PC主要解决的单点故障问题,并减小阻塞,由于一旦参与者没法及时收到来自协调者的信息以后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。可是这种机制也会致使数据一致性问题,由于,因为网络缘由,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时以后执行了commit操做。这样就和其余接到abort命令并执行回滚的参与者之间存在数据不一致的状况。
上面提到的关于协调者在实践过程当中由谁来担任是个问题,通常来说这个协调者是异步的,能够在参与者和协调者之间双向通讯的,有良好的消息传递机制,可以保证消息稳定投递。故而通常协调者的担任者是高性能的消息中间件例如RocketMq、Kafka、RabbitMq等。
如图就是一个2PC的实践: