分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以下是一些常见的分布式事务实现方式:
一、两阶段提交(2PC)
- 阶段一:准备阶段
- 事务协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并等待参与者的响应。
- 参与者执行事务操作,但不提交,将 undo 和 redo 信息记入事务日志中,然后向协调者返回“可以提交”或“不可以提交”的响应。
- 阶段二:提交阶段
- 如果所有参与者都返回“可以提交”,那么协调者向所有参与者发送“正式提交”的命令,参与者执行提交操作并释放事务处理过程中使用的资源。
- 如果有任何一个参与者返回“不可以提交”,那么协调者向所有参与者发送“回滚事务”的命令,参与者利用 undo 信息执行回滚操作,释放事务处理过程中占用的资源。
优点:
- 尽量保证了数据的强一致性。
缺点:
- 同步阻塞问题,在执行过程中,所有参与节点都是事务阻塞型的,当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
- 单点故障问题,一旦事务协调者发生故障,整个系统将不可用。
- 数据不一致问题,在二阶段提交的阶段二中,当协调者向参与者发送 commit 请求之后,发生了局部网络异常或者在发送 commit 请求过程中协调者发生了故障,这会导致只有一部分参与者接受到了 commit 请求,而在这部分参与者接到 commit 请求之后就会执行 commit 操作,但是其他部分未接到 commit 请求的机器则无法执行事务提交,于是整个分布式系统便出现了数据不一致性的现象。
二、三阶段提交(3PC)
三阶段提交在两阶段提交的基础上进行了改进,主要是为了解决两阶段提交的同步阻塞和数据不一致问题。
- 阶段一:CanCommit 阶段
- 事务协调者向所有参与者发送一个包含事务内容的 canCommit 请求,询问是否可以执行事务提交操作。
- 参与者收到 canCommit 请求后,如果认为可以执行事务,则返回 yes 响应,并进入预备状态,否则返回 no 响应。
- 阶段二:PreCommit 阶段
- 如果所有参与者都返回 yes 响应,那么协调者向所有参与者发送 preCommit 请求,参与者接收到 preCommit 请求后,执行事务操作,并将 undo 和 redo 信息记录到事务日志中,然后向协调者返回 ACK 响应。
- 如果有任何一个参与者返回 no 响应或者协调者在一定时间内没有收到所有参与者的响应,那么协调者向所有参与者发送 abort 请求,参与者接收到 abort 请求后,利用 undo 信息执行事务回滚操作,并释放事务处理过程中占用的资源。
- 阶段三:DoCommit 阶段
- 如果协调者收到了所有参与者的 ACK 响应,那么协调者向所有参与者发送 doCommit 请求,参与者接收到 doCommit 请求后,正式执行事务提交操作,并释放事务处理过程中占用的资源。
- 如果协调者在一定时间内没有收到所有参与者的 ACK 响应,那么协调者会进行超时处理,向所有参与者发送 abort 请求,参与者接收到 abort 请求后,利用 undo 信息执行事务回滚操作,并释放事务处理过程中占用的资源。
优点:
- 降低了阻塞范围,在第一阶段和第二阶段中,参与者在等待协调者的指令时不会一直阻塞,而是有超时机制。
- 解决了单点故障问题,在第三阶段中,即使协调者出现故障,参与者也可以根据超时机制自行提交或回滚事务。
缺点:
- 仍然可能出现数据不一致问题,在第三阶段中,如果协调者发送了 doCommit 请求后出现网络分区,部分参与者接收到了请求并提交了事务,而另一部分参与者没有接收到请求,那么这两部分参与者的数据就会不一致。
三、补偿事务(TCC)
TCC 是一种基于业务层面的分布式事务解决方案,它将一个分布式事务拆分成三个阶段:Try、Confirm、Cancel。
- Try 阶段
- 尝试执行业务,完成所有业务检查(一致性),预留必须业务资源(准隔离性)。
- Confirm 阶段
- 确认执行业务操作,不做任何业务检查,只使用 Try 阶段预留的业务资源。Confirm 操作满足幂等性要求,Confirm 失败后需要进行重试。
- Cancel 阶段
- 取消执行业务操作,释放 Try 阶段预留的业务资源。Cancel 操作满足幂等性要求,Cancel 失败后需要进行重试。
优点:
- 最终一致性,通过不断重试来保证事务的最终一致性。
- 性能较好,因为事务的执行是在业务层面进行控制的,可以根据业务需求进行优化。
缺点:
- 开发成本高,需要业务系统自己实现 Try、Confirm、Cancel 三个阶段的逻辑,对业务系统的侵入性较大。
四、消息事务(基于消息中间件)
- 事务发起方
- 执行本地事务。
- 向消息中间件发送一条事务消息,这条消息处于“待确认”状态。
- 消息中间件将事务消息持久化存储,但不向消息接收方投递消息。
- 事务发起方本地事务执行成功后,向消息中间件发送“确认提交”消息;如果本地事务执行失败,则向消息中间件发送“回滚事务”消息。
- 消息中间件
- 收到“确认提交”消息后,将事务消息标记为“可投递”状态,并向消息接收方投递消息。
- 收到“回滚事务”消息后,删除事务消息。
- 事务接收方
- 接收到消息后,执行本地事务。
- 本地事务执行成功后,向消息中间件发送“确认消费”消息;如果本地事务执行失败,则不发送任何消息,等待消息中间件进行重试。
优点:
- 实现了最终一致性,通过消息中间件的重试机制来保证事务的最终完成。
- 对业务系统的侵入性较小,只需要在业务系统中处理消息即可。
缺点:
- 依赖消息中间件的可靠性,如果消息中间件出现故障,可能会导致事务失败。
- 可能会出现消息重复消费的问题,需要业务系统进行幂等性处理。