浅析分布式事务中的2PC和3PC

分布式事务

大型的分布式系统架构都会涉及到事务的分布式处理的问题,基原本说,分布式事务和普通事务都有一个共同原则:数据库

  • A(Atomic) 原子性,事务要么一块儿完成,要么一块儿回滚
  • C(Consistent) 一致性,提交数据先后数据库的完整性不变
  • I(Isolation) 隔离性,不一样的事务相互独立,不互相影响
  • D(Duration)持久性,数据状态是永久的

另一个设计原则,分布式系统要符合如下原则:网络

  • C(Consistent)一致性,分布式系统中存在的多个副本,在数据和内容上要如出一辙
  • A(Availability)高可用性,在有限时间内保证系统响应
  • P(Partition tolerance)分区容错性,一个副本或一个分区出现宕机或其余错误时,不影响系统总体运行

因为在设计分布式系统时,难以保证CAP所有符合,最多保证其中两个,例如在一个分布式系统中:
要保证系统数据库的强一致性,须要跨表跨库占用数据库资源,在复杂度比较高的状况下,耗时难以保证,就会出现可用性没法保证的状况。架构

故而又出现了BASE理论异步

  • Basic Available基本可用,分布式系统在出现故障时,容许损失部分可用功能,保证核心功能可用
  • Soft state柔性状态,容许系统存在中间状态,这个状态不影响系统可用性
  • Eventually Consistent 最终一致性 指通过一段时间以后,全部数据状态保持一致的结果

实际上BASE理论是基于AP的一个扩展,一个分布式事务不须要强一致性,只须要达到一个最终一致性就能够了。分布式

分布式事务就是处理分布式中各个节点的数据操做,使之可以在节点相互隔离的状况下完成多个节点数据的一致性操做。性能

分步式事务 - 2PC

2PC即二阶段提交,在这里须要了解两个概念spa

  • 参与者:参与者即各个实际参与事务的节点,这些节点相互隔离,彼此不知道对方是否提交事务。
  • 协调者:收集和管理参与者的事务信息,负责统一管理节点信息,也就是分布式事务中的第三方。

准备阶段,也称投票阶段

准备阶段中,协调者向参与者发送precommit的消息,参与者在本地执行事务逻辑,若是没有超时以及运行无误,那么会记录redo和undo日志,将ack信息发送给协调者,当协调者收到全部节点参与者发送的ack信息时,准备进入下一阶段,不然会发送回滚信息给各个节点,各个节点根据以前记录好的undo信息回滚,本次事务提交失败。设计

提交阶段

提交阶段中,协调者已经收到全部节点的应答信息,接下来发送commit消息给各个节点,通知各个节点参与者能够提交事务,各个参与者提交完毕后一一发送完成信息给协调者,并释放本地占用的资源,协调者收到全部完成消息后,完成事务。日志

二阶段提交的图示以下:
图片描述中间件

二阶段提交的问题

二阶段提交虽然可以解决大多数的分布式事务的问题,且发生数据错误的几率极小,但仍然有如下几个问题:

  • 单点故障:若是协调者宕机,那么参与者会一直阻塞下去,若是在参与者收到提交消息以前协调者宕机,那么参与者一直保持未成功提交的状态,会一直占用资源,致使同时间其余事务可能要一直等待下去。
  • 同步阻塞问题:由于参与者是在本地处理的事务,是阻塞型的,在最终commit以前,一直占用锁资源,若是遇到时间较长而协调者未发回commit的状况,那么会致使锁等待。
  • 数据一致性问题:假如协调者在第二阶段中,发送commit给某些参与者失败,那么就致使某些参与者提交了事务,而某些没有提交,这就致使了数据不一致。
  • 二阶段根本没法解决的问题:假如协调者宕机的同时,最后一个参与者也宕机了,当协调者经过从新选举再参与到事务管理中时,它是没有办法知道事务执行到哪一步的。

针对于以上提出的一些问题,衍生出了3PC。

分布式事务 - 3PC

3PC即三阶段提交协议。

图片描述

3PC相对于2PC,有了如下变化:

  • 引入超时机制,在参与者和协调者中都加入了各自的超时策略。
  • 加入了一个新的阶段,canCommit,因此阶段分红了三个:canCommit、PreCommit、DoCommit。

CanCommit

这是一个准备阶段,在这一阶段中,协调者向参与者发送CanCommit消息,参与者接收后,根据自身资源状况判断是否能够执行事务操做,若是能够而且未超时,则发送yes给协调者,反之,协调者会中断事务。

PreCommit

这是预备阶段,在这一阶段中,协调者向参与者发送PreCommit消息,参与者接收后,会执行事务操做,记录undo和redo日志,事务执行完毕后会将Ack消息发送给协调者,协调者在未超时的状况下收集全部参与者的信息,不然中断事务,通知全部参与者Abort消息。

DoCommit

当全部参与者Ack消息完毕以后,协调者会确认发送DoCommit消息给每个参与者,执行提交事务。原则上全部参与者执行提交完毕以后,须要发送Committed给协调者,协调者完成事务。不然协调者中断事务,参与者接收abort消息会根据以前记录的undo回滚。
但也要注意,此阶段中若是参与者没法及时收到协调者发来的Docommit消息时,也会自行提交事务,由于从几率上来说,PreCommit这个阶段可以不被abort说明所有节点均可以正常执行事务提交,因此通常来说单个节点提交不影响数据一致性,除非极端状况。

2PC 和 3PC的区别

相对于2PC,3PC主要解决的单点故障问题,并减小阻塞,由于一旦参与者没法及时收到来自协调者的信息以后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。可是这种机制也会致使数据一致性问题,由于,因为网络缘由,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时以后执行了commit操做。这样就和其余接到abort命令并执行回滚的参与者之间存在数据不一致的状况。

消息中间件

上面提到的关于协调者在实践过程当中由谁来担任是个问题,通常来说这个协调者是异步的,能够在参与者和协调者之间双向通讯的,有良好的消息传递机制,可以保证消息稳定投递。故而通常协调者的担任者是高性能的消息中间件例如RocketMq、Kafka、RabbitMq等。

如图就是一个2PC的实践:
图片描述

相关文章
相关标签/搜索