分布式事务

事务特性

ACID

  • 原子性(Atomicity): 事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生
  • 一致性(Consistency): 事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。
  • 隔离性(Isolation): 多个事务并发访问时,事务之间是隔离的。一个事务不应该影响其他事务的运行结果。
  • 持久性(Durability): 在事务完成以后,该事务对数据库所做的修改便持久的保存在数据库之中,不会被回滚。

一、 一致性理论

CAP理论

3个要素最多只能同时满足两个,不可兼得。其中,分区容忍性又是不可缺少的。

  • 一致性(Consistency): 分布式环境下多个节点的数据是否强一致
  • 可用性(Availability): 分布式服务能一直保证可用状态。当用户发出一个请求后,服务能在有限时间内返回结果。
  • 分区容忍性(Partition Tolerance): 特指对网络分区的容忍性。

BASE理论

  • 基本可用(BasicallyAvailable): 分布式系统出现故障时,允许损失部分的可用性来保证核心可用。
  • 软状态(SoftState): 允许分布式系统存在中间状态,该中间状态不会影响到系统的整体可用性。
  • 最终一致性(EventualConsistency): 是指分布式系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。

二、一致性模型

  • 强一致性: 数据更新成功后,任意时刻所有副本中的数据都是一致的,一般采用同步的方式
  • 弱一致性: 数据更新成功后,系统不承诺可以立即读到最新写入的值,也不承诺具体多久之后可以读到
  • 最终一致性: 弱一致性的一种形式,数据更新成功后,系统不承诺立即可以返回最新写入的值,但是保证最终会返回上一次更新操作的值

分布式事务解决方案

在介绍方案之前先了解下XA规范。XA是由X/Open组织提出的分布式事务的规范。XA接口函数由中间件实现,事务管理器(TM)用它来通知事务的开始、结束以及提交、回滚等。

X/Open DTP模型由以下几部分组成:

  • 应用程序(Application, AP)
  • 事务管理器(Transaction Manager, TM)
  • 资源管理器(Resource Manager, RM)
  • 通讯资源管理器(Communication Resource Manager, CRM)

资源管理器(RM)是数据库,通讯资源管理器(CRM)是消息中间件。

分布式事务的适用场景

在同一个事务上下文中需要协调多种资源(数据库,以及消息主题或队列)

2PC方案 - 强一致性

two-phase-commit,两阶段提交

AP向TM发送commit请求时,

  • 第一阶段(准备阶段) TM会依次询问RM是否已准备好,RM会回答READY、READ_ONLY和NOT_READY。如果有NOT_READY,则整个事务回滚。如果有READ_ONLY,会在提交阶段排除掉。
  • 第二阶段(提交阶段) TM向RM发送消息,通知RM提交或回滚。RM执行相应操作并释放事务执行过程中的锁资源。
缺点
  1. 同步阻塞问题。执行过程中所有参与节点都是事务阻塞型的,当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态
  2. 单点故障。由于协调者的重要性,一旦协调者发生故障参与者会一直阻塞下去
  3. 数据不一致。在阶段二中,由于TM宕机或者网络发生问题导致只有一部分RM收到commit请求时,收到commit请求的RM会执行commit操作,而没有收到commit请求的RM则无法执行请求,导致系统出现数据不一致。
  4. 太过保守。如果TM未收到RM的响应,TM只能根据自身的超时机制判断是否要终止事务。

2PC没有设计较为完善的容错机制,任意一个节点的失败都会导致整个事务的失败。

3PC方案

步骤
  1. CanCommit TM向RM发送CanCommit请求。如果所有RM都反馈YES,则进入PreCommit阶段。如果有RM反馈NO,或者超时未响应,则执行事务的中断,TM会向所有RM发送abort请求。这一阶段,如果RM超时未收到TM的PreCommit请求,会自动执行中断。
  2. PreCommit TM向RM发送PreCommit请求。RM收到请求后执行事务操作,并将undo和redo信息记录到事务日志中。如果RM成功执行了事务操作,则向TM发送ACK响应,等待TM的DoCommit请求。如果TM没有收到RM的ACK响应,或者RM响应超时,则TM执行事务中断操作。
  3. DoCommit TM收到了所有RM的ACK响应,向RM发送DoCommit请求。RM收到请求后,执行事务提交操作。如果RM超时未收到TM的请求,也会自动执行事务的提交操作。之后RM释放事务资源,并向TM发送ACK响应。TM收到所有ACK响应之后,完成事务。
改进
  • 增加超时机制
  • 解决单点故障,减少资源阻塞。
存在问题

在参与者收到PreCommit请求之后,发生了网络分区。如果之后TM执行了事务中断,该参与者由于超时收不到响应会自动执行提交,导致数据不一致。

相较于2PC,3PC主要解决了单点故障问题,并减少了阻塞。因为当RM无法收到TM的消息时,会在超时之后自动执行提交或回滚操作,不会一直持有事务资源并处于阻塞状态。

eBay事件队列方案 - 最终一致性

将需要分布式处理的任务通过消息或者日志的方式来异步执行,通过本地事务的ACID特性来保证消息的存储,再通过业务规则进行失败重试。它要求Consumer端是幂等的。首先由业务逻辑保证幂,比如修改订单状态。如果业务逻辑无法保持幂等,则需要增加一个去重表或者类似实现。比如加款操作。对于这种就需要消息有一个id,可以基于消息的id做去重。

适用于异步更新

TCC(Try-Confirm-Cancel)补偿模式 - 最终一致性

由发起方发起事务,参与者提供提交和回滚方法。发起者记录调用链,根据异常发生的位置调用相应参与者的回滚方法。回滚方法需要保持幂等。 例: A调用B、C、D。如果调C的commit()方法时,发生了异常,则调用B的rollback()方法。如果调用D的commit()方法时,发生了异常,则调用B和C的rollback()方法。

适用于同步调用

关键要素
  • 服务调用链必须被记录下来
  • 每个服务提供者都需要提供一组业务逻辑相反的操作,互为补偿,同时回滚操作要保证幂等
  • 必须按失败原因执行不同的回滚策略。特别是调用超时。

总结

2PC和3PC都无法彻底解决分布式的一致性问题。生产中较多采用事件队列方案和TCC方案,保证系统的可用性,承诺数据的最终一致。

results matching ""

    No results matching ""