关于后端:ChatGPT万字长文理解透彻分布式事务

分布式事务是指在分布式环境下,对多个数据资源进行并行操作时,须要保持数据资源之间的一致性和完整性,同时具备ACID的个性。在分布式系统中,因为存在多个数据存储节点、网络提早、可用性等问题,导致分布式事务的实现相比拟于单节点事务要更加简单和艰难。

常见的分布式事务解决方案包含

  1. 两阶段提交(Two-Phase Commit, 2PC):事务协调者(TC)首先向所有参与者(P)收回“预提交”(prepare)申请,各参与者对音讯进行确认操作。如果所有参与者都能失常执行,则协调者向参与者收回“正式提交”申请,各参与者将事务提交到本地数据库,返回确认音讯。如果该过程中呈现任何一个参与者无奈提交,则会进行回滚操作,使得全局事务回滚到最后的状态。
  2. 弥补事务(TCC):TCC事务将一个事务以尽可能简略的模式合成为三个步骤——试着去执行它,查看是否能够提交,如果不能提交,则回滚曾经执行的动作。在TCC事务中,须要实现try、confirm和cancel三个接口,通过调用confirm、cancel接口实现提交和回滚操作。
  3. Saga事务:Saga是一种反对可撤销和部署在多个实例之间的长事务处理模式。Saga事务将长事务拆分为多个小事务,每个小事务之间不再强制保障强一致性,而是通过异步音讯通信的形式进行程序化解决,从而升高了零碎的复杂度和开发成本。
  4. 音讯队列事务:在消息中间件的反对下,将音讯的生产者和消费者进行事务性单干。

以上解决方案都有其实用场景和实现细节,须要依据具体的业务需要进行抉择。同时,在利用分布式事务时还须要思考到数据一致性、可靠性、性能、可扩展性等方面的问题。

两阶段提交

两阶段提交(Two-Phase Commit,2PC)是实现分布式事务的一种较为传统的形式,它通过引入一个协调者(Coordinator)来协调多个参与者(Participant)的提交行为,从而保障分布式事务的原子性和一致性。

2PC的过程如下所示:

阶段一:

  1. 协调者向所有分布式事务参与者发送“canCommit”申请。
  2. 各参与者接管到申请后,会相应的执行数据筹备工作。如果参与者在执行筹备工作时发现有不可解决的谬误,则向协调者发送“NO”响应。
  3. 如果所有参与者都胜利的执行了筹备工作,则向协调者发送“YES”响应。

阶段二:

  1. 如果协调者在阶段一收到了所有参与者的“YES”响应,则向所有参与者发送“doCommit”申请。参与者收到申请后执行事务提交,并向协调者返回“ACK”示意提交胜利。
  2. 如果协调者在阶段一或二的任一阶段收到了任何一个参与者的“NO”响应或超时,则向所有参与者发送“doAbort”申请,参与者执行事务回滚操作,并向协调者返回“ACK”示意回滚胜利。

2PC的具体实现有以下几点须要留神:

  1. 参与者在接管到“canCommit”申请后,须要记录下此时的以后状态(能够提交或不可提交),以便于在回滚操作时进行信息复原。
  2. 协调者在期待参与者响应时要思考超时状况的解决。如果等待时间过长,则须要对尚未响应的参与者进行解决。
  3. 2PC模型可能会存在“单点故障”的问题,即如果协调者呈现问题,则整个分布式事务都会进入一种无奈解决的状态。因而,须要采纳数据备份、容灾等措施来升高协调者呈现故障的概率。

总之,2PC尽管具备原子性和一致性的特点,但其实现复杂度较高,同时存在一些可能导致性能降落和可用性升高的问题,因而须要依据具体的业务场景进行衡量和抉择。

举例说明

以转账业务为例子,介绍应用两阶段提交(2PC)实现分布式事务的过程。

假如有两个账户A和B,咱们须要在分布式环境下实现从账户A向账户B转账的业务。具体过程如下:

  1. 协调者(Coordinator)向账户A和账户B的参与者(Participant)发送“canCommit”申请。
  2. 账户A和B的参与者接管到申请后进行账户余额扣减和减少操作,并记录下以后状态。如果参与者执行过程中出现异常或者产生网络故障等状况,则向协调者发送“NO”响应。
  3. 如果A和B的参与者都胜利的实现了账户余额变动操作,则向协调者发送“YES”响应。
  4. 协调者依据收到的参与者响应决定事务提交或回滚操作。

    • 如果所有参与者的响应都是“YES”,则协调者向所有参与者发送“doCommit”申请,各参与者执行提交操作并返回“ACK”示意提交胜利。
    • 如果任意一个参与者的响应为“NO”或协调者期待响应超时,则协调者向所有参与者发送“doAbort”申请,各参与者执行回滚操作并返回“ACK”示意回滚胜利。

例如,账户A和B的Participator胜利解决账户余额变动操作,向Coordinator发送了“YES”响应。协调者收到两个参与者的“YES”响应后,决定提交事务。协调者向账户A和B的Participator发送“doCommit”申请,各参与者收到申请后执行事务提交操作,返回“ACK”示意提交胜利。

如果账户A的余额有余,导致账户A的Participator向协调者发送了“NO”响应,则协调者向所有参与者发送“doAbort”申请,各参与者执行事务回滚操作,并返回“ACK”示意回滚胜利。

以上就是应用两阶段提交(2PC)实现分布式事务的过程,能够保障分布式环境下数据的一致性和完整性。

TCC

TCC(Try-Confirm-Cancel)是一种实现分布式事务的较为风行的形式,它将一个分布式事务拆解成“尝试”(Try)、“确认”(Confirm)和“撤销”(Cancel)三个阶段,从而保障了事务的原子性和一致性。

具体来说,TCC实现分布式事务的过程如下:

  1. Try阶段:进行第一阶段的预处理,查看所有业务参与者的执行条件,查看通过后将所有状态缓存到预提交日志中。
  2. Confirm阶段:在第二阶段进行业务提交,如果有执行失败,则返回谬误,须要从新尝试,直到确认并执行胜利,状态提交胜利后将对应的缓存删除,开释资源。
  3. Cancel阶段:在第二阶段,业务须要回滚,则在第三阶段进行回滚解决,勾销的同时开释被锁住的资源。

TCC的实现须要从以下几个方面进行思考:

  1. 幂等性解决:在Try和Confirm阶段须要保障幂等性,同时须要解决反复申请的状况。
  2. 可恢复性解决:在整个分布式事务中如果出现异常或者是网络故障等非正常状况,须要通过后盾定期的恢复程序对分布式事务进行重试解决,保障分布式事务的失常提交和撤销。
  3. 长事务和非长事务:TCC不适用于超长事务,因为在尝试期间对资源的占用可能会导致资源的不可用性。 对于较短的事务,则不会受到这个问题的影响。
  4. 数据库的反对:TCC须要对分布式数据库进行反对,或者应用相似于音讯队列的形式进行事务提交。
  5. 状态并发管制:在TCC模式中,预提交日志的状态会始终存在一段时间,其余构架须要在这段时间内对状态进行异步更新和读取,须要解决并发和锁的问题。

总之,TCC是实现分布式事务的较为罕用的形式之一,绝对于2PC而言,它的性能和可靠性都更加优良,实现的复杂度绝对2PC要低。

举例说明

假如咱们有一个转账业务,须要在分布式环境下实现,应用TCC实现分布式事务的过程如下:

  1. Try阶段:查看两个账户的余额是否足够,如果余额有余则不能进行转账操作,尝试锁定两个账户并预扣除转账金额,缓存此次转账记录和锁定信息到Try日志中。
  2. Confirm阶段:实现转账操作,开释锁定资源。如果两个账户的余额都足够,则进行理论的转账操作,记录转账流水和对应的余额变动。如果转账操作执行胜利,则删除Try日志中记录的缓存。如果转账操作执行失败,则进行业务回滚,撤销Try日志中记录的缓存。
  3. Cancel阶段:进行第三阶段解决,将预扣除金额返回给原账户,删除Try日志中记录的缓存并开释锁定的资源,确保曾经锁定的账户最终没有被转出。

例如,A账户向B账户转移1000元,应用TCC实现分布式事务的过程如下:

  1. A账户和B账户的参与者在Try阶段查看A账户余额足够,锁定A账户并预扣除1000元;B账户锁定胜利。
  2. A账户和B账户的参与者在Confirm阶段执行转账操作,记录转账流水和余额变动,开释锁定,最终确认转账操作胜利。
  3. 如果在Try阶段时,A账户余额有余,则进行Cancel阶段解决,将预扣除的1000元退回到A账户中,开释锁定。

以上就是应用TCC实现分布式事务的具体过程了。TCC通过将分布式事务拆分成“尝试”、“确认”和“撤销”三个阶段,以最小的开销保障了分布式事务的可靠性和一致性。

Saga

Saga是一种基于弥补机制的分布式事务解决方案。它通过将整个事务拆解成一系列的部分事务,每个部分事务负责更新本人的本地状态,并通过发送compensating action来实现事务的撤销操作。Saga的核心思想是以“最小承诺”缩小分布式事务的范畴,从而打消了分布式事务的复杂性,更加实用于微服务架构中的分布式场景。

应用Saga实现分布式事务的过程如下:

  1. 定义Saga事务:定义Saga事务中的部分事务和compensating action。每个部分事务都会有本人的业务逻辑和状态治理,并且须要实现compensating action以实现事务的撤销操作,保障整个事务的可靠性。
  2. 执行Saga事务:Saga事务由一个协调器进行管制,它负责调用每个部分事务,并且在每个部分事务实现后查看后果,如果任何部分事务呈现了失败,协调器将调用compensating action进行撤销操作。
  3. Saga事务状态:Saga事务的状态通过每个部分事务的执行后果进行推动,在一系列的部分事务和弥补操作中进行转移。
  4. 高可用性:Saga事务须要保障高可用性,因而须要应用leader选举或主备模式来保障协调器的高可用性,以避免单点故障导致整个事务呈现失败。

举例

例如,上面是一个Saga事务的示例:

  1. 订单服务提交订单。
  2. 领取服务执行领取操作,如果领取失败则执行compensating action进行撤销操作。
  3. 发货服务执行发货操作,如果发货失败则执行compensating action进行撤销操作。
  4. 物流服务执行更新物流信息操作。
  5. 审核服务执行订单审核操作,如果审核失败则执行compensating action进行撤销操作。
  6. 订单服务发送订单确认音讯。
  7. 客户服务实现客户告诉。

在这个示例中,如果任何一个部分事务呈现失败,Saga事务的协调器将调用compensating action来撤销操作,以保障整个事务的一致性和可靠性。

总之,Saga是一种基于弥补机制的分布式事务解决方案,它提供了一种缩小事务范畴的计划,从而打消分布式事务中的复杂性,更适宜于微服务架构中的分布式场景。应用Saga时须要定义Saga事务、执行Saga事务、Saga事务状态治理和保障高可用性。

音讯事务

分布式事务中的音讯事务,通常指的是在事务执行过程中所应用的音讯队列的事务。实现音讯事务的形式次要有两种,别离是本地音讯事务和分布式音讯事务。

1、本地音讯事务:

本地音讯事务是在音讯发送方和接管方所在的数据库事务中,通过音讯队列来实现数据的异步操作。在本地音讯事务中,发送方发送音讯时,将音讯插入到一个本地音讯表中,并在以后数据库事务中进行提交。如果后续在事务执行过程中须要回滚,也须要将曾经发送的音讯删除。接管方在收到音讯后,须要在本地数据库事务中进行解决。

2、分布式音讯事务:

分布式音讯事务须要音讯队列反对分布式事务的性能。常见的有基于音讯队列内嵌事务的分布式音讯事务和基于两阶段提交的分布式音讯事务。其中基于音讯队列内嵌事务的形式,比方 Kafka 中的事务反对,通过音讯队列内嵌事务来实现分布式事务的性能。在应用该形式时,音讯的发送方和接管方都须要在同一个事务中进行,如果事务呈现问题,则音讯会被回滚。

基于两阶段提交的分布式音讯事务,则将音讯队列作为一个参与者,与数据库事务一起参加分布式事务的解决。在该模式下,在分布式事务提交之前须要进行两个阶段的合作:第一阶段中,记录音讯的相干信息并将音讯发送到音讯队列;第二阶段中,音讯队列接管事务协调器发送的音讯,确认音讯能够发送,并期待最终的确认信息。如果分布式事务提交胜利,则音讯队列会将音讯发送进来;如果分布式事务回滚,则音讯队列不会发送音讯。

总的来说,实现分布式事务的音讯事务须要思考到音讯的发送、接管以及在分布式事务中的合作等方面,采纳适合的技术和计划来实现。

本地音讯事务

在实现分布式事务时,能够采纳本地事务表的模式来实现。具体实现形式如下:

  1. 在利用中定义本地事务表。能够应用 MySQL 或者其余数据库来存储本地事务表,该表中须要蕴含以下字段:
  • xid:全局惟一标识事务 ID
  • branch_id:分支事务 ID
  • status:分支事务状态(提交、回滚、未知)
  • participant_id:参与者 ID
  • create_time:分支事务创立工夫
  • update_time:分支事务更新工夫
  • rollback_info:回滚信息
  1. 在利用中应用应用 Spring Boot 集成分布式事务框架实现分布式事务,比方应用 Seata。
  2. 实现分布式事务的参与者,须要在本地事务表中记录对应的分支事务。 以后节点的事务参与者须要在本地事务表中插入一条记录,示意以后节点参加了全局事务,并更新状态为“未知”。
  3. 在分布式事务提交时,须要先提交本地事务,而后依据本地事务的后果,提交或者回滚全局事务。在本地事务提交时,须要将以后节点参加的分支事务状态的状态改为“提交”,并将回滚信息置空。
  4. 如果本地事务失败,全局事务须要回滚。在回滚时,须要将参与者的分支事务状态批改为“回滚”,并将回滚信息更新到本地事务表中。这时,全局事务协调器将会回滚所有分支事务的状态。

Spring Boot 集成 Seata 能够应用 Seata 官网提供的 Spring Boot Starter,具体应用办法可参考 Seata 的官网文档。

MQ事务

应用音讯队列(MQ)实现分布式事务,通常是采纳异步确保的形式。具体形式如下:

  1. 在分布式事务中应用音讯队列来进行数据的异步操作,同时将音讯队列作为分布式事务的参与者之一。
  2. 将音讯发送方和接管方的事务拆散开来,别离作为两个分支事务处理。在本地事务执行实现后,将要发送的音讯插入到音讯队列中,期待音讯队列将音讯发送到接管方。
  3. 当音讯发送方实现本地事务后,若事务提交胜利,则须要将音讯发送到音讯队列中,并保障音讯可靠性,保障音讯发送不会失败。如果发送失败,则须要将音讯长久化到本地数据库,并期待后续重发。
  4. 对于接管方,须要在本地事务中对接管到的音讯进行解决。如果解决胜利,则须要将音讯从音讯队列中删除,否则须要将音讯更改状态,保障音讯反复生产时的正确性。
  5. 如果在分支事务执行过程中呈现失败(比方音讯发送失败),须要对分支事务进行回滚,同时须要保障音讯队列不会将该音讯发送到接管方。在音讯队列中实现该性能,经常须要采纳阻塞式发送。

须要留神的是,应用音讯队列实现分布式事务时,因为波及到异步操作,因而须要保障音讯的可靠性,比方音讯长久化、重试机制等。同时,也须要思考到可能呈现音讯反复生产的状况,须要在音讯队列中进行判重等操作。

具体实现时,能够应用消息中间件(比方 RabbitMQ、Kafka)来实现分布式事务的音讯队列。此外,在应用分布式事务时,也能够思考分布式事务框架,比方 Seata、Hmily 等,它们能够反对分布式事务的协调、治理,提供更便捷的分布式事务实现形式。

Seata

Seata是一种开源的分布式事务解决方案,它提供高效的多数据源、跨服务端的分布式事务管理能力。Seata将每个事务定义为一个全局惟一的XID(X/Open XA规范中的标识符),通过将每个参与方的local transaction纳入全局事务的管理体系中,实现分布式事务的可靠性,保障多个事务操作的原子性、一致性和隔离性。

应用Seata实现分布式事务的过程如下:

  1. 服务端代码的革新:在所有的服务中,对于须要参加分布式事务的办法进行革新,应用Seata提供的@GlobalTransactional注解标注上事务的类型,主动开启全局事务。
  2. Seata代理的染指:客户端须要引入Seata代理,Seata代理将染指原有的分布式系统,拦挡业务申请并向Seata Server注册事务分支,以获取全局惟一的XID。
  3. 分布式事务执行:开始执行分布式事务,服务中的每一个分支都会通过与Seata协调器的交互进行状态的更新,并在事务实现时上报状态,依据事务执行的后果告诉Seata进行后续的操作。
  4. Seata Server的治理:蕴含事务的开始、弥补、提交、回滚、查问等操作,对立治理全局事务的状态。

例如,上面是应用Seata实现转账业务的示例:

  1. 当用户A向用户B转账时,A服务和B服务须要应用@GlobalTransactional注解对事务进行治理。Seata代理从两个服务中获取XID。
  2. 而后A服务从A用户账户中扣除金额,B服务减少金额。在扣除和减少金额过程中,Seata将本地事务注册为分布式事务,调配分支ID,通过异步传递分支状态并期待分支状态告诉。
  3. 如果其中一方失败,Seata从上一个告诉的状态中检索分支,并向所有未实现工作发送事务回滚指令(暂未理论提交)。事务回滚指令胜利发送时则进行回滚(失常状态下这将是通过异步音讯来实现)。
  4. 如果所有分支工作都胜利,则Seata回滚底层资源管理器中记录的任何长期写入,并向所有未实现事务发送事务提交指令(失常状况下,这将通过异步音讯来实现)。

以上就是应用Seata实现分布式事务的过程,通过Seata对部分事务的承诺和向Seata Server的注册治理,以达到全局事务的管制和治理,实现了分布式事务的可靠性和一致性。

Seata反对三种分布式事务模式,别离是AT、TCC和SAGA,每种模式都有其实用场景,能够依据理论需要抉择应用。

1、AT模式

AT(Alter Table)模式利用数据库提供的ACID事务机制,可能缩小代码的批改量,最大限度地利用已有的资源,并提供高性能和简便治理。在AT模式下,Seata代理会拦挡每一个波及到数据库的SQL操作,当分支事务进行提交时,Seata会主动将所有批改的数据都写入redo log,并在回滚时将这些操作删除。AT模式实用于业务逻辑简略,对实时性有要求的场景。

2、TCC模式

TCC(Try Confirm Cancel)模式是一种基于业务逻辑实现的分布式事务模式。TCC模式的原理是将一个残缺交易拆分成三个阶段——预留资源(try)、执行操作(confirm)和勾销操作(cancel),每个阶段对应一个事务操作,通过自定义的业务逻辑实现事务的治理。在TCC模式下,Seata代理会拦挡业务申请,同时依据业务逻辑调用try、confirm、cancel的办法。TCC模式实用于业务逻辑简单,须要定制化事务管理和数据处理的场景。

3、SAGA模式

SAGA(Saga pattern)模式是一种基于弥补机制的分布式事务模式。相比于AT和TCC模式,SAGA模式更加实用于零碎与零碎之间的分布式事务场景。SAGA模式将简单的分布式事务拆分成一个个小的本地事务和弥补操作,并通过弥补操作保障整个事务的一致性。在SAGA模式下,Seata会依据应用程序的Saga定义动静地创立和治理micro transactions,从而实现不同服务之间的交互和事务的解决。SAGA模式实用于不同服务之间存在多阶段业务流程,须要依据业务逻辑实现事务管理的场景。

总之,Seata反对三种分布式事务模式,每种模式都适宜不同的利用场景和业务需要。在利用中抉择适合的事务模式十分重要,能够依据具体业务需要抉择AT、TCC和SAGA中的一种或几种来实现分布式事务。

AT

在Spring Boot中应用Seata的AT模式,大略须要以下步骤:

  1. 引入相干依赖
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.4.2</version>
</dependency>
  1. 配置文件批改

在 application.yml 或 application.properties 中增加以下Seata配置项:

spring:
  application:
    name: xxx-service   # 这里是你的服务名,须要与Seata Server上的注册信息对应
  cloud:
    alibaba:
      seata:
        tx-service-group: my_test_tx_group   # 这里指定Seata服务的事务组名
        service:
          vgroup:
            my_test_tx_group: "default"   # 这里指定Seata Server默认的事务组名
          group:
            my_test_tx_group:   # 把这个服务注册到Seata Server的事务组名
              default:
                annotation-interceptor-order: 1
                undo-data-validation: true
                mode: AT  # 这里指定AT模式
                log-store: db
                lock:
                  type: DB
                  # 记得把上面的DB配置改成你的数据库配置
                  db:
                    datasource: druid   # javax.sql.DataSource类型,倡议应用集成连接池,例如druid、hikari等
                    ...
                report-retry-count: 5
  1. 补充Seata配置文件

在 Seata Server 的 registry.conffile.conf 文件中,须要退出对本服务的配置:

[registry]
# example: file:/registry
type: file
nacos:
  serverAddr: localhost:8848
  namespace: please_set_your_namespace
  cluster: default

client:
  ...
  customizedRegistryClassName: io.seata.registry.FileRegistry
  applicationId: my_test_tx_group
  txServiceGroup: my_test_tx_group
  env: test

# file registry config
file:
  name: file.conf

[registry-file]
type: file

serverList: file://registry

[service]
vgroupMapping.my_test_tx_group=default
default.grouplist=file://127.0.0.1:8091
enableDegrade=false
disableGlobalTransaction=false
  1. 让业务办法反对Seata的分布式事务

在须要应用Seata的分布式事务的办法上加上@GlobalTransactional注解,则此办法即变成了全局事务,如下所示:

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderDAO orderDAO;

    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    @Override
    public Integer createOrder(OrderDTO orderDTO) {
        // 业务逻辑
    }
}

其中,@GlobalTransactional注解的name属性标注此次全局事务的名称,rollbackFor属性标注回滚的异样类型。

最初,配置好之后运行服务,如果一切正常,你就能够在 Seata Server 的事务列表中看到你的服务退出了一个新的分布式事务了。

通过以上步骤,咱们就能够在Spring Boot利用中应用Seata的AT模式实现分布式事务管理。

TCC

在Spring Boot中应用Seata的TCC模式,大略须要以下步骤:

  1. 引入相干依赖
<dependency>
  <groupId>io.seata</groupId>
  <artifactId>seata-spring-boot-starter</artifactId>
  <version>1.4.2</version>
</dependency>
  1. 配置文件批改

在 application.yml 或 application.properties 中增加以下Seata配置项:

spring:
  application:
    name: xxx-service   # 这里是你的服务名,须要与Seata Server上的注册信息对应
  cloud:
    alibaba:
      seata:
        tx-service-group: my_test_tx_group   # 这里指定Seata服务的事务组名
        service:
          vgroup:
            my_test_tx_group: "default"   # 这里指定Seata Server默认的事务组名
          group:
            my_test_tx_group:   # 把这个服务注册到Seata Server的事务组名
              default:
                annotation-interceptor-order: 1
                undo-data-validation: true
                mode: TCC  # 这里指定TCC模式
                log-store: none
                lock:
                  type: db   # TCC模式锁的类型须要设为db
                  db:
                    ...
                report-retry-count: 5
  1. 补充Seata配置文件

在 Seata Server 的 registry.conffile.conf 文件中,须要退出对本服务的配置:

[registry]
# example: file:/registry
type: file
nacos:
  serverAddr: localhost:8848
  namespace: please_set_your_namespace
  cluster: default

client:
  ...
  customizedRegistryClassName: io.seata.registry.FileRegistry
  applicationId: my_test_tx_group
  txServiceGroup: my_test_tx_group
  env: test

# file registry config
file:
  name: file.conf

[registry-file]
type: file

serverList: file://registry

[service]
vgroupMapping.my_test_tx_group=default
default.grouplist=file://127.0.0.1:8091
enableDegrade=false
disableGlobalTransaction=false
  1. 让业务办法反对Seata的分布式事务

在须要应用Seata的分布式事务的办法上加上@TccTransaction注解,接着实现该办法对应的三个办法(try、confirm、cancel),同时这三个办法须要应用@Compensable注解,如下所示:

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderDAO orderDAO;

    @TccTransaction(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
    @Override
    public boolean createOrder(OrderDTO orderDTO) {
        // TCC try办法,不须要做什么
        return true;
    }

    @Compensable(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
    public void tryCreateOrder(OrderDTO orderDTO) {
        // TCC try办法,预留资源
        orderDAO.insert(orderDTO);
    }

    @Compensable(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
    public void confirmCreateOrder(OrderDTO orderDTO) {
        // TCC confirm办法,提交分布式事务
    }

    @Compensable(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
    public void cancelCreateOrder(OrderDTO orderDTO) {
        // TCC cancel办法,回滚分布式事务
        orderDAO.delete(orderDTO.getId());
    }
}

其中,@TccTransaction注解在办法级别上表明以后办法须要反对分布式事务,同时指定了try办法对应的confirm办法和cancel办法。

而@Compensable注解则在子办法级别上标注了以后办法须要纳入分布式事务的治理,同时指定了该办法在confirm和cancel时须要执行的办法。

最初,配置好之后运行服务,如果一切正常,你就能够在 Seata Server 的事务列表中看到你的服务退出了一个新的分布式事务了。

通过以上步骤,咱们就能够在Spring Boot利用中应用Seata的TCC模式实现分布式事务管理。

Saga

在 Spring Boot 中应用 Seata 的 Saga 模式,须要以下步骤:

1、引入相干依赖

<dependency>
  <groupId>io.seata</groupId>
  <artifactId>seata-spring-boot-starter</artifactId>
  <version>1.4.2</version>
</dependency>

2、配置文件批改

在 application.yml 或 application.properties 中增加以下 Seata 配置项:

# Seata 配置
spring:
  application:
    name: xxx-service # 这里是你的服务名,须要与 Seata Server 上的注册信息对应
  cloud:
    alibaba:
      seata:
        tx-service-group: my_test_tx_group # 这里指定 Seata 服务的事务组名,须要与 Seata Server 上的设置统一
        service:
          vgroup:
            my_test_tx_group: "default" # 这里指定 Seata Server 默认的事务组名
          group:
            my_test_tx_group: # 把这个服务注册到 Seata Server 上的事务组名
              default:
                mode: SAGA # 指定 saga 模式
                health-check: false
                report-retry-count: 5
                max-commit-retry-timeout: 300
                max-rollback-retry-timeout: 30

3、配置 Seata Server 的 endpoint

在 Seata Server 的配置文件 registry.conf 中,须要为每个要退出 Saga 模式的服务,配置其 endpoint。这里以两个服务为例:

[registry]
# example: file:/registry
type: file
nacos:
  serverAddr: localhost:8848
  namespace: please_set_your_namespace
  cluster: default

client:
  ...
  customizedRegistryClassName: io.seata.registry.FileRegistry
  applicationId: my_test_tx_group
  txServiceGroup: my_test_tx_group
  env: test

# file registry config
file:
  name: file.conf

[registry-file]
type: file

serverList: file://registry

[service]
vgroupMapping.my_test_tx_group=default
default.grouplist=file://127.0.0.1:8091,file://127.0.0.1:8092
enableDegrade=false
disableGlobalTransaction=false

[saga]
store.mode=db  # saga 模式须要指定 store.mode 为 db
store.db.driver-class-name=com.mysql.cj.jdbc.Driver   # 应用 MySQL 数据库存储 Saga 状态
store.db.url=jdbc:mysql://localhost:3306/seata_saga?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
store.db.username=root
store.db.password=123456                                    
store.db.min-conn=5
store.db.max-conn=30
store.db.global-table-name=seata_global_table   # 全局事务表名,默认值为global_table
store.db.branch-table-name=seata_branch_table   # 分支事务表名,默认值为branch_table
store.file.path=/seata/saga  # 应用文件存储 Saga 状态

其中,store.mode 须要指定为 dbstore.db 指定数据库相干信息。

4、编写 Saga 并增加 @SagaTransactional 注解

在须要实现 Saga 模式的业务操作方法上增加 @SagaTransactional 注解,并编写与之对应的 Saga 对象及其步骤执行逻辑。

上面是一个示例:

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDAO orderDAO;

    /**
     * 创立订单
     */
    @SagaTransactional
    @Override
    public void createOrder(OrderDTO orderDTO) {
        // 扣减商品库存
        ProductReduceStockDTO productReduceStockDTO = new ProductReduceStockDTO(orderDTO.getProductId(), orderDTO.getAmount());
        productClient.reduceStock(productReduceStockDTO);

        // 下单
        orderDAO.insert(orderDTO);

        // 发送领取事务
        SagaRequest sagaRequest = new SagaRequest();
        sagaRequest.setServiceName("account-service");
        sagaRequest.setMethodName("pay");
        sagaRequest.setPayloads(new Object[]{orderDTO.getUserId(), orderDTO.getTotalAmount()});

        SagaDefinition<OrderDTO> sagaDefinition = new SagaDefinition<>();
        sagaDefinition.setSagaName("create-order-saga");
        sagaDefinition.setPayload(orderDTO);
        sagaDefinition.setSteps(Arrays.asList(
                new SagaStep<>("product-service", "reduceStock", productReduceStockDTO),
                new SagaStep<>("order-service", "insert", orderDTO),
                new SagaStep<>(sagaRequest)
        ));

        SagaContext start = SagaContext.start();
        SagaManager.executeSaga(sagaDefinition, start);
    }

    @CompensableConfirm
    public void createOrderConfirm(OrderDTO orderDTO) {
        // do nothing
    }

    @CompensableCancel
    public void createOrderCancel(OrderDTO orderDTO) {
        orderDAO.delete(orderDTO.getId());
    }
}

其中,@SagaTransactional 注解在办法上示意这是一个 Saga 分布式事务操作。

SagaDefinition 示意一个 Saga 分布式事务的定义,蕴含了该 Saga 的名称、开始时的 payload(启动该 Saga 执行的参数)、以及一系列的步骤,每个步骤都是一个 SagaStep 对象。

@CompensableConfirm@CompensableCancel 注解别离示意执行确认和勾销操作。这些办法的实现该当和原始操作相同,以确保分布式事务的完整性。

5、运行服务

配置好 Seata Server 和相干配置信息之后,就能够启动利用并运行测试了。如果一切正常,你就能够在 Seata Server 的 Saga 实例中看到对应的实例,并能够查看各个步骤的执行后果。

通过以上步骤,咱们就能够在 Spring Boot 利用中应用 Seata 的 Saga 模式实现分布式事务管理。

须要留神哪些方面

在实现分布式事务时,须要留神以下几个方面:

  1. 数据库的一致性:分布式事务波及到多个数据库,须要确保各个数据库操作的一致性。这能够通过在事务开始时对数据库进行锁定,保障在这个事务完结前其余事务无法访问受锁定的数据,从而保障了数据的一致性。
  2. 事务的可靠性:分布式事务须要确保事务的可靠性,即在各个节点产生故障或者网络谬误时,可能保障事务的正确执行。这能够通过应用分布式事务协定或者保障事务的幂等性来实现。
  3. 事务的性能:分布式事务绝对于本地事务,会带来一些额定的性能开销。因而,在实现分布式事务时须要思考性能问题。例如能够通过分片、异步操作等形式来优化性能。
  4. 基础设施的反对:分布式事务须要底层基础设施的反对,例如分布式锁、音讯队列、分布式计算等。因而,在实现分布式事务时须要思考基础设施的反对,并抉择适合的技术栈。
  5. 代码的可维护性:分布式事务波及到多个节点的操作,因而代码的可维护性十分重要。在实现分布式事务时须要思考代码的可维护性,例如能够通过模块化、对立接口等形式来进步代码的可维护性。

面试常问

以下是一些对于分布式事务的常见面试考点:

  1. 什么是分布式事务?

分布式事务是指逾越多个计算机或者零碎的一种事务,并且在多个数据库、文件系统或其余系统资源上逾越多个事务管理器或协调器。分布式事务须要保证数据在分布式环境下的一致性。

  1. 分布式事务的实现形式有哪些?

分布式事务的实现形式有以下几种形式:

  • 2PC (Two-Phase Commit):通过协调者来治理事务的提交和回滚,实现多个数据库、过程之间的一致性。
  • 3PC (Three-Phase Commit):2PC 的改进版,解决了 2PC 中的阻塞问题。
  • TCC (Try-Confirm-Cancel):在分布式环境中,将一个分布式事务拆分成多个本地事务,容许服务自行处理事务的确认或勾销。
  • Saga:将一个分布式事务拆分成多个子事务,每个子事务都有本人的本地事务管理器来解决本人的事务状态,在子事务之间传递音讯来保障最终一致性。
  • 本地音讯表:用于处理事务间的关系,通过本地音讯表保护各个事务的状态,在事务提交时才向内部零碎收回音讯。
  1. 什么是 2PC?

2PC (Two-Phase Commit) 是一种分布式事务的实现形式。在 2PC 中,协调者将会在两个阶段来提交事务:prepare 和 commit。在 prepare 阶段,协调者会向所有参与者告诉分布式事务的筹备状态,并要求各个参与者在本地筹备好事务。在 commit 阶段,如果所有参与者在 prepare 阶段都反馈了已筹备好事务的状态,协调者会告诉所有参与者提交事务,否则协调者会申请所有参与者回滚事务。

  1. 2PC 的长处和毛病是什么?

2PC 的长处是:

  • 反对强一致性,所有节点的状态雷同。
  • 协调者负责整个事务的治理,绝对简略。
  • 标准化实现,易于开发调试。

2PC 的毛病是:

  • 阻塞性问题,要期待所有参与者反馈后果后能力实现事务。
  • 单点故障,协调者呈现问题会导致整个事务无奈持续进行。
  • 吞吐量和可扩展性存在瓶颈,因为协调者负责整个事务的解决,因而无奈扩大申请的吞吐量。
  1. 可靠消息最终一致性框架的实现形式有哪些?

可靠消息最终一致性框架的实现形式有以下几种形式:

  • TCC:Try-Confirm-Cancel 的缩写。尝试先执行须要近程执行的事务;如果胜利,则进行执行确认,否则则进行执行勾销,从而实现事务的回滚操作。
  • Saga:将一个分布式事务拆分成多个子事务,每个子事务都有本人的本地事务管理器来解决本人的事务状态,在子事务之间传递音讯来保障最终一致性。
  • 本地音讯表:用于处理事务间的关系,通过本地音讯表保护各个事务的状态,在事务提交时才向内部零碎收回音讯。

本文由mdnice多平台公布

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理