分布式事务和分布式锁

分布式事务

强一致的分布式事务

XA协议、二阶段2PC(prepare、commit)、三阶段3PC提交。

XA协议

XA 就是 X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。 XA 接口函数由数据库厂商提供。

X/Open DTP 模型( 1994 )包括应用程序( AP )、事务管理器( TM )、资源管理器( RM )、通信资源管理器( CRM )四部分。

2PC

二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。第一阶段:准备阶段(投票阶段)和第二阶段:提交阶段(执行阶段)。

2PC面临的问题:同步阻塞问题,以及协调者故障后造成的数据部分一致问题。

3PC

三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本。

3PC分为can_commit、pre_commit、commit/cancel三个阶段。

如果因为协调者或网络问题,导致参与者迟迟不能收到来自协调者的commit或rollback请求,那么参与者将不会如两阶段提交中那样陷入阻塞,而是等待超时后继续commit。相对于两阶段提交虽然降低了同步阻塞,但仍然无法避免数据的不一致性。

柔性事务

根据BASE理论,达到最终一致性。

DNS 就是一个典型的最终一致性系统。

在工程实践上,为了保障系统的可用性,互联网系统大多将强一致性需求转换成最终一致性的需求,并通过系统执行幂等性的保证,保证数据的最终一致性。

最终一致性

TCC补偿机制(Try、Confirm/Cancel)

其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。

TCC施行步骤

  1. Try 阶段主要是对业务系统做检测及资源预留。
  2. Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行Confirm阶段时,默认 Confirm阶段是不会出错的。
  3. Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

TCC与2PC协议比较:

  1. 位于业务服务层而非资源层
  2. 没有单独的准备(Prepare)阶段,Try操作兼备资源操作与准备能力
  3. Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度)
  4. 较高开发成本

本地消息表

类似于可靠消息方案。

消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。

消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。

生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。

优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。

缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

事务消息

通过使用RocketMQ,第一阶段发送Prepared消息时,会拿到消息的地址,第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改消息的状态。

其他

  1. XA协议是一个基于数据库的分布式事务协议,其分为两部分:事务管理器和本地资源管理器。事务管理器作为一个全局的调度者,负责对各个本地资源管理器统一号令提交或者回滚。二阶提交协议(2PC)和三阶提交协议(3PC)就是根据此协议衍生出来而来。目前 Oracle、Mysql 等数据库均已实现了XA接口。
  2. 两段提交(2PC)就是进行两个阶段的提交:第一阶段,准备阶段(投票阶段) ;第二阶段,提交阶段(执行阶段)。
  3. 三段提交(3PC)是对两段提交(2PC)的一种升级优化,3PC在2PC的第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前,各参与者节点的状态都一致。同时在协调者和参与者中都引入超时机制,当参与者各种原因未收到协调者的commit请求后,会对本地事务进行commit,不会一直阻塞等待,解决了2PC的单点故障问题,但3PC 还是没能从根本上解决数据一致性的问题。
  4. 3PC 的三个阶段分别是CanCommit、PreCommit、DoCommit。
  5. TCC与2PC的思想很类似,事务处理流程也很类似,但2PC 是应用于在DB层面,TCC则可以理解为在应用层面的2PC,是需要开发者编写业务逻辑来实现的。
  6. TCC的核心思想是:"针对每个操作都要注册一个与其对应的确认(Try)和补偿(Cancel)"。