凤凰架构-全局事务、共享事务、分布式事务

周志明《凤凰架构:构建可靠的大型分布式系统》
https://icyfenix.cn/

包括:
XA、JTA、两阶段提交、三阶段提交、CAP、BASE理论。
实现分布式事务的三种解决方案,可靠消息队列、TCC、SAGA事务。

  • 可靠消息队列:简单、无法解决隔离性问题
  • TCC:编码实现业务隔离性,但要求技术可控性(预留资源接口),硬编码可以使用Seata
  • SAGA事务:编码实现业务隔离性和补偿机制,不要求技术可控性,硬编码可以使用Seata

全局事务

在本节里,全局事务被限定为一种适用于单个服务使用多个数据源场景的事务解决方案。

为了解决分布式事务的一致性问题,X/Open组织提出了一套名为X/Open XA(XA 是 eXtended Architecture 的缩写)的处理事务架构,其核心内容是定义了全局的事务管理器(Transaction Manager,用于协调全局事务)和局部的资源管理器(Resource Manager,用于驱动本地事务)之间的通信接口。

XA 接口是双向的,能在一个事务管理器和多个资源管理器(Resource Manager)之间形成通信桥梁,通过协调多个数据源的一致动作,实现全局事务的统一提交或者统一回滚。

JTA(Java Transaction API)是基于 XA 模式在 Java 语言中的实现了全局事务处理的标准。

XA 将事务提交拆分成为两阶段过程,两阶段式提交(2 Phase Commit,2PC):

  • 准备阶段(又叫作投票阶段,对于数据库来说,它与本地事务中真正提交的区别只是暂不写入最后一条 Commit Record 而已,并不立即释放隔离性,即仍继续持有锁)
  • 提交阶段(又叫作执行阶段,对于数据库来说,这个阶段的提交操作应是很轻量的,仅仅是持久化一条 Commit Record 而已,通常能够快速完成)

缺点:

  • 单点问题:协调者宕机,所有参与者都必须一直等待
  • 性能问题:两段提交过程中,所有参与者相当于被绑定成为一个统一调度的整体,期间要经过两次远程服务调用,三次数据持久化(准备阶段写重做日志,协调者做状态持久化,提交阶段在日志写入 Commit Record)
  • 一致性风险:前面已经提到,两段式提交的成立是有前提条件的,当网络稳定性和宕机恢复能力的假设不成立时,仍可能出现一致性问题。

为了缓解两段式提交协议的一部分缺陷,具体地说是协调者的单点问题和准备阶段的性能问题,后续又发展出了“三段式提交”(3 Phase Commit,3PC)协议。
三段式提交把原本的两段式提交的准备阶段再细分为两个阶段,分别称为 CanCommit、PreCommit,把提交阶段改称为 DoCommit 阶段。

共享事务

共享事务(Share Transaction)是指多个服务共用同一个数据源。这里有必要再强调一次“数据源”与“数据库”的区别:数据源是指提供数据的逻辑设备,不必与物理设备一一对应。

如果直接将不同数据源视为不同的数据库,那完全可以用全局事务或者下一讲要学习的分布式事务来实现。

如果针对每个数据源连接的都是同一个物理数据库的特例,一种理论可行的方案是,直接让各个服务共享数据库连接。同一个应用进程中共享数据库连接并不困难,但不同服务节点共享数据库连接很难做到,为了实现共享事务,就必须新增一个中间角色。

这在分布式的场景下是个伪需求,你有充足理由让多个微服务去共享数据库,那就必须找到更加站得住脚的理由,来向团队解释拆分微服务的目的是什么。

分布式事务

分布式事务(Distributed Transaction)特指多个服务同时访问多个数据源的事务处理机制。

CAP

分布式系统(distributed system)的最大难点,就是各个节点的状态如何同步。CAP 定理是这方面的基本定理。

  • 一致性(Consistency):代表在任何时刻、任何分布式节点中所看到的数据都是符合预期的。

  • 可用性(Availability):代表系统不间断地提供服务的能力。密切相关两个指标:可靠性(平均无故障时间:MTBF)和可维护性(平均可修复时间:MTTR)。

  • 分区容忍性(Partition Tolerance):代表分布式环境中部分节点因网络原因而彼此失联(即与其他节点形成“网络分区”)时,系统仍能正确地提供服务的能力。

  • 如果放弃分区容忍性(CA without P),意味着我们将假设节点之间通信永远是可靠的。永远可靠的通信在分布式系统中必定不成立的。主流的 RDBMS(关系数据库管理系统)集群通常就是采用放弃分区容错性的工作模式。

  • 如果放弃可用性(CP without A),意味着我们将假设一旦网络发生分区,节点之间的信息同步时间可以无限制地延长,此时,问题相当于退化到前面“全局事务”中讨论的一个系统使用多个数据源的场景之中,我们可以通过 2PC/3PC 等手段,同时获得分区容忍性和一致性。著名的 HBase 也是属于 CP 系统。

  • 如果放弃一致性(AP without C),意味着我们将假设一旦发生分区,节点之间所提供的数据可能不一致。选择放弃一致性的 AP 系统目前是设计分布式系统的主流选择,因为 P 是分布式网络的天然属性,而 A 通常是建设分布式的目的。目前大多数 NoSQL 库和支持分布式的缓存框架都是 AP 系统,如Redis集群。

CAP、ACID 中讨论的一致性称为“强一致性”(Strong Consistency)。把牺牲了 C 的 AP 系统,叫做“最终一致性”(Eventual Consistency)。它是指,如果数据在一段时间内没有被另外的操作所更改,那它最终将会达到与强一致性过程相同的结果,有时候面向最终一致性的算法,也被称为“乐观复制算法”。

BASE理论

BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。

BASE 分别是基本可用性(Basically Available)、柔性事务(Soft State)和最终一致性(Eventually Consistent)的缩写。

  • 基本可用性(Basically Available):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
  • 柔性事务(Soft State):允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是 CAP 理论中的数据不一致。
  • 最终一致性(Eventually Consistent):系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。

可靠消息队列

前面这种靠着持续重试来保证可靠性的操作,在计算机中就非常常见,它有个专门的名字,叫做“最大努力交付”(Best-Effort Delivery),比如 TCP 协议中的可靠性保障,就属于最大努力交付。

支持分布式事务的消息框架,如 RocketMQ,原生就支持分布式事务操作。

TCC

可靠消息队列虽然能保证最终的结果是相对可靠的,过程也足够简单(相对于 TCC 来说),但整个过程完全没有任何隔离性可言,有一些业务中隔离性是无关紧要的,但有一些业务中缺乏隔离性就会带来许多麻烦。譬如:超售。

TCC 是另一种常见的分布式事务机制,它是“Try-Confirm-Cancel”三个单词的缩写。

TCC 的实现过程分为了三个阶段:

  • Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好全部需用到的业务资源(保障隔离性)。
  • Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。Confirm 阶段可能会重复执行,因此本阶段所执行的操作需要具备幂等性。
  • Cancel:取消执行阶段,释放 Try 阶段预留的业务资源。Cancel 阶段可能会重复执行,也需要满足幂等性。

它是一种业务侵入性较强的事务方案,要求业务处理过程必须拆分为“预留业务资源”和“确认 / 释放消费资源”两个子过程。

TCC 其实有点类似 2PC 的准备阶段和提交阶段,但 TCC 是位于用户代码层面,而不是在基础设施层面,这为它的实现带来了较高的灵活性,可以根据需要设计资源锁定的粒度。TCC 在业务执行时只操作预留资源,几乎不会涉及锁和资源的争用,具有很高的性能潜力。但是 TCC 并非纯粹只有好处,它也带来了更高的开发成本和业务侵入性,意味着有更高的开发成本和更换事务实现方案的替换成本。

通常我们并不会完全靠裸编码来实现 TCC,而是基于某些分布式事务中间件(譬如阿里开源的Seata)去完成,尽量减轻一些编码工作量。

SAGA事务

TCC 事务具有较强的隔离性,避免了“超售”的问题,而且其性能一般来说是本篇提及的几种柔性事务模式中最高的,但它仍不能满足所有的场景。TCC 的最主要限制是它的业务侵入性很强,不止是它需要开发编码配合所带来的工作量,而更多的是指它所要求的技术可控性上的约束。譬如,网银支付,通常也就无法完成冻结款项、解冻、扣减这样的操作。

SAGA 事务基于数据补偿代替回滚的解决思路。大致思路是把一个大事务分解为可以交错运行的一系列子事务集合。每个子事务都应该是或者能被视为是原子行为;为每一个子事务设计对应的补偿动作。

两种恢复策略:
正向恢复(Forward Recovery):T1,T2,…,Ti(失败),Ti(重试)…,Ti+1,…,Tn
反向恢复(Backward Recovery):T1,T2,…,Ti(失败),Ci(补偿),…,C2,C1。

与 TCC 相比,SAGA 不需要为资源设计冻结状态和撤销冻结的操作,补偿操作往往要比冻结操作容易实现得多。

SAGA 事务通常也不会直接靠裸编码来实现,一般也是在事务中间件的基础上完成,前面提到的 Seata 就同样支持 SAGA 事务模式。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值