分布式事务

分布式事务是指是指事务的发起者、参与者、数据资源服务器以及事务管理器分别位于分布式系统的不同节点之上
参与者通过网络通信来达到分布式一致性,网络通信不可避免出现失败、超时的情况

XA Specification

基于资源层的底层分布式事务解决方案,对业务的入侵度较低

有些数据分片框架或者中间件也支持XA协议,兼容性、普遍性好 但并发性能比较差, 基于XA的分布式事务如果要严格保证ACID,实际需要事务隔离级别为SERLALIZABLE

基于消息的分布式事务

通过消息系统来通知其他事务参与方自己事务的执行状态,有效的将事务参与方解耦,各个参与方可以异步执行

难点: 解决本地事务执行和消息发送的一致性:两者要同时执行成功或者同时取消执行

场景: 原则上只接受下游分支事务的成功,不接受事务的回滚,如果失败就要一直重试,适用于对最终一致性敏感度较低的业务场景

可能会因为接收方的消息堆积导致长时间的数据不一致

基于事务消息

事务消息发送成功后,处于 prepared 状态,不能被订阅者消费,等到事务消息的状态更改为可消费状态后,下游订阅者才可以监听到次消息。支持事务消息的 MQ 系统有一个定时扫描逻辑,扫描出状态仍然是“待发送”状态的消息,并向消息的发送方发起询问,询问这条事务消息的最终状态如何并根据结果更新事务消息的状态。

提供事务消息状态查询接口

基于本地消息

如果所依赖的 MQ 系统不支持事务消息,那么可以采用本地消息的分布式模式

事务的发起方维护一个本地消息表,业务执行和本地消息表的执行处在同一个本地事务中。业务执行成功,则同时记录一条“待发送”状态的消息到本地消息表中。系统中启动一个定时任务定时扫描本地消息表中状态为“待发送”的记录,并将其发送到 MQ 系统中,如果发送失败或者超时,则一直发送,知道发送成功后,从本地消息表中删除该记录

最大努力通知型分布式事务

基于 MQ 系统的一种解决方案,但是不要求 MQ 消息可靠(如支付宝支付成功通知),通过引入定期校验机制来对最终一致性做兜底,对业务侵入性较低、对 MQ 系统要求较低,实现比较简单,适合于对最终一致性敏感度比较低、业务链路较短的场景,比如跨平台、跨企业的系统间的业务交互

基于补偿的事务

事务补偿机制 : 在事务链中的任何一个正向事务操作,都必须存在一个完全符合回滚规则的可逆事务

TCC

将资源层的二阶段提交协议转换到业务层,成为业务模型中的一部分,核心思想是通过对资源的预留,尽早释放对资源的加锁,如果事务可以提交,则完成对预留资源的确认,如果事务要回滚,则释放预留的资源

业务设计和代码都会变复杂(需要业务方把功能的实现上由一个接口拆分为三个),但性能、隔离性都很好

业务方在设计实现上要遵循三个策略(网络中的通信失败或超时)

  1. 允许空回滚:try 失败或者没有执行 try 操作的参与方收到 cancel 请求时,要进行空回滚操作
  2. 保持幂等性:重复调用参与方的 confirm/cancel 方法,因此需要这两个方法实现上保证幂等性
  3. 防止资源悬挂:参与方侧 try 请求比 cancel 请求更晚到达的情况,cancel 会执行空回滚而确保事务的正确性,但是此时 try 方法也不可以再被执行

支持 TCC 事务的开源框架有:ByteTCC、Himly、TCC-transaction。

Saga模式

Saga 和 TCC 一样,也是一种补偿事务,但是它没有 try 阶段,而是把分布式事务看作一组本地事务构成的事务链

事务链中的每一个正向事务操作,都对应一个可逆的事务操作。Saga 事务协调器负责按照顺序执行事务链中的分支事务,分支事务执行完毕,即释放资源。如果某个分支事务失败了,则按照反方向执行事务补偿操作。如果补偿失败了,就一直重试,补偿操作可以优化为并行执行

不保证事务隔离性,本地事务提交后变更就对其他事务可见了。其他事务如果更改了已经提交成功的数据,可能会导致补偿操作失败。比如扣款失败,但是钱已经花掉了,业务设计上需要考虑这种场景并从业务设计上规避这种问题

不完美补偿,补偿操作会留下之前原始事务操作的痕迹,需要考虑对业务上的影响

要求业务设计实现上遵循三个策略:

  1. 允许空补偿:网络异常导致事务的参与方只收到了补偿操作指令,因为没有执行过正常操作,因此要进行空补偿
  2. 保持幂等性:事务的正向操作和补偿操作都可能被重复触发,因此要保证操作的幂等性
  3. 防止资源悬挂:网络异常导致事务的正向操作指令晚于补偿操作指令到达,则要丢弃本次正常操作,否则会出现资源悬挂问题

适合于业务流程长的长事务的场景,实现上对业务侵入低,所以非常适合微服务架构的场景。同时 Saga 采用的是一阶段提交模式,不会对资源长时间加锁,不存在“木桶效应”,所以采用这种模式架构的系统性能高、吞吐高

阿里云分布式事务相关工具

DRDS 基于MySQL的XA实现,使用方便,但并发性能低

GTS 全局事务服务 就提了个本地事务和mq能在一起提交

seata

通过全局锁实现了写隔离与读隔离

  • 一阶段本地事务提交前,需要确保先拿到 全局锁
  • 拿不到 全局锁 ,不能提交本地事务。
  • 拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁

开启本地事务,拿到本地锁,更新操作,本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。第二阶段提交释放 全局锁

全局锁相当于写锁,但比由数据库实现性能好一些,
Seata(AT 模式)的默认全局隔离级别是 读未提交,会出现脏读,要拿读已提交需要全局锁,可以按业务做调整,但性能会好一些。全局锁会额外增加死锁的风险,但如果出现死锁,会不断进行重试,最后靠等待全局锁超时

性能比XA好一点,第一阶段的提交会释放本地锁,但还存在全局锁,会阻塞写,但不影响默认的读未提交
XA的prepare是数据库实现的锁,而且要求事务串行执行

你可能感兴趣的:(分布式事务)