? ? ? ? ? Seata是一个开源的分布式事务解决方案,旨在简化分布式事务的实现。它提供了一种简单而强大的方式来管理分布式事务,在分布式应用程序中保持数据的一致性和可靠性。
? ? ? ? ?在传统的单体应用程序中,数据库事务可以很容易地实现。但是,在分布式系统中,事务管理可以变得更加复杂。分布式事务要求跨多个服务协调和管理事务操作,确保所有参与者的操作要么全部成功,要么全部回滚以保持一致性。
? ? ? ?Seata采用了一种两阶段提交(2PC)的协议来实现分布式事务。它包含三个核心组件:事务协调器(Transaction Coordinator,TC)、事务管理器(Transaction Manager,TM)和资源管理器(Resource Manager,RM)。
事务协调器(TC):负责协调和管理分布式事务的执行。事务管理器(TM)是分布式事务的入口点,负责事务的发起和提交。
资源管理器(RM):管理着事务涉及的所有资源,包括数据库、消息队列、缓存等。
? ? ? ? ? ?Seata 是一种分布式事务解决方案,它用于解决分布式系统中的事务一致性问题。在分布式系统中,由于数据分散在不同的节点上,当一个业务操作需要跨多个节点时,需要保证这些节点上的数据操作要么全部成功,要么全部回滚,以保持数据的一致性。
使用 Seata 可以带来以下好处:
保持数据的一致性:Seata 提供了分布式事务管理的机制,能够确保跨多个节点的数据操作要么全部成功,要么全部回滚,保持数据的一致性。
提高系统性能:Seata 通过优化事务提交和回滚的过程,减少了分布式事务的开销,提高了系统的性能。
提供强一致性和高可用性:Seata 使用了一套高效的协调机制,能够在分布式环境下提供强一致性和高可用性的服务。
简化开发和维护:Seata 提供了一套简单易用的 API,开发人员可以很方便地在现有的业务系统中集成分布式事务管理功能,减少了开发和维护的复杂性。
? ? ? ? ?分布式事务是指跨多个数据源或服务的事务操作,通常涉及多个数据库或多个微服务的操作。与单个数据库的事务不同,分布式事务需要在多个参与方之间保持数据的一致性和完整性。而Spring声明式事务只针对单个数据库的事务操作。
? ? ? ?在分布式系统中,每个项目通常都会有自己的数据库事务,但是当多个项目需要进行跨多个数据库或服务的事务操作时,就需要引入分布式事务框架,如Seata。Seata是一个开源的分布式事务解决方案,可以提供分布式事务的管理和控制,保证数据的一致性和完整性。
? ? ? ?通过Seata,可以在多个参与方之间进行协调和同步,实现分布式事务的操作。Seata采用了两阶段提交的方式来保证分布式事务的一致性,第一阶段为事务的准备阶段,各个参与方会执行本地事务,并将事务的执行结果提交给Seata;第二阶段为事务的提交阶段,Seata会根据各个参与方的提交结果来进行最终的事务提交或回滚。
? ? ?Seata的主要构成包括:
事务协调器(TC):事务协调器是Seata的核心组件,负责协调全局事务的提交和回滚。它通过与业务逻辑代码进行交互,收集各个分支事务的执行结果,并在所有分支事务执行成功时提交全局事务,任何分支事务执行失败时回滚全局事务。
事务管理器(TM):事务管理器负责全局事务的开启、提交和回滚。在Seata中,每个微服务都会有一个事务管理器,它通过与事务协调器交互,实现全局事务的控制。
资源管理器(RM):资源管理器负责管理分支事务的提交和回滚。在Seata中,每个微服务都会有一个资源管理器,它与事务协调器和事务管理器通信,协调分支事务的执行和结果反馈。
事务日志存储(Storage):事务日志存储模块负责存储事务的相关日志信息。Seata支持多种事务日志存储方案,包括数据库存储、文件存储等。事务日志存储模块提供了事务日志的写入和读取接口,用于支持事务的持久化和恢复。
全局事务ID生成器(AT):全局事务ID生成器负责生成全局唯一的事务ID。每个全局事务在启动时都会被分配一个唯一的事务ID,用于标识该事务的执行过程。
注册中心(Registry):注册中心负责管理Seata的各个组件的注册和发现。它提供了服务注册和发现的功能,使得各个组件能够找到对应的服务进行通信。
? ? ? Seata的运行原理可以分为三个关键步骤:全局事务的发起、全局事务的提交与回滚、分支事务的提交与回滚。
全局事务的发起: 当一个业务需要跨多个服务进行数据更新时,首先需要创建一个全局事务。发起者(通常是客户端或者服务端)向Seata发起请求,Seata为该请求生成一个唯一的全局事务ID,并将该ID与该请求绑定。全局事务ID被传递到所有涉及的服务中,以保证这些服务在执行业务操作时,都能够参与到该全局事务中。
全局事务的提交与回滚: 在全局事务内,每个参与者都是一个分支事务的发起者。当每个参与者需要对数据进行更新时,它们会向Seata发起请求,Seata为该请求生成一个唯一的分支事务ID,并将该ID与全局事务ID进行关联。参与者执行实际的业务操作,并将分支事务ID和操作结果返回给Seata。当所有参与者都完成了业务操作后,全局事务的提交或者回滚就会被触发。
分支事务的提交与回滚: 当全局事务被提交时,Seata会向每个参与者发送提交请求。参与者根据传递的分支事务ID,执行相应的提交操作。如果全局事务被回滚,Seata会向每个参与者发送回滚请求,参与者根据传递的分支事务ID,执行相应的回滚操作。这样,全局事务的状态就能够被正确地更新。
? ? ? ? 此外,Seata还提供了分布式事务恢复的机制。当系统发生异常情况导致分布式事务未能正常完成时,Seata会通过日志进行重试和恢复操作,确保事务的正确性。
当account操作失败时,要让已经操作完成的order撤销操作,也要让stroage撤销操作
? ?
AT模式运行过程
? ?1.事务的发起方(TM)会向事务协调器(TC)申请一个全局事务id,并保存
? ?2.Seata会管理事务中所有相关的参与方的数据源,将数据操作之前和之后的镜像都保存在undo_log表中,这个表是seata框架规定的,方便提交(commit)或回滚(roll back)
? 3.事务的发起方(TM)会连同全局id一起通过远程调用运行资源管理器(RM)中的方法
? 4.资源管理器(RM)接收到全局id,并运行指定的方法,将运行的状态同步到事务协调器(TC)
? 5.如果运行整体没有发生异常,发起方(TM)会通过事务协调器通知所有分支,将本次事务所有对数据库的影响真正生效,
如果任何一个参与者发生异常,那么都会通知事务协调器,再由事务协调器通知有分支,根据undo_log表中保存的信息,撤销(回滚)即将正式影响数据库的数据
? 下面逐一进行详细解释与说明:
? ? ? ?TCC事务模式的主要应用场景是业务逻辑比较复杂、不适合使用XA或SAGA事务模式的情况。它的作用是通过将一个大事务拆解为多个小事务,增加了事务的可控性,并且可以保证数据的最终一致性。
? ? ? ?SAGA事务模式适用于长时间执行和具有连续性操作的业务场景。它的作用是通过将一个大的操作拆解为多个独立的片段,并通过事件驱动的方式实现数据的一致性。
? ? ?XA事务模式适用于需要强一致性的分布式系统场景,但它对数据库和中间件的支持要求较高,并且在性能方面存在一定的开销。
? ? ? 总结:
? ? ? ? ? ? XA | ? ? ? ? ? ? ? ? ?AT | ? ? ? ? ? ? ? ?TCC | ? ? ? ? ? ? ? ? SAGA | |
一致性 | 强一致 | 弱一致 | 弱一致 | 最终一致 |
隔离性 | 完全隔离 | 基于全局锁隔离 | 基于资源预留隔离 | 无隔离 |
代码侵入 | 无 | 无 | 有 | 有 |
性能 | 差 | 好 | 很好 | 很好 |
场景 | 对一致性、隔离性有高要求的业务 | 基于关系型数据库的大多数分布式事务场景都可以 | 对性能要求较高的事务有非关系型数据库要参与的事务 | 业务流程长、业务流程多参与者包含其它公司或遗留系统服务,无法提供 TCC模式要求的三个接口 |
? ?https://github.com/seata/seata/releases
? https://github.com/seata/seata/releases/download/v1.4.2/seata-server-1.4.2.zip
? ? ?<dependency>
? ? <groupId>io.seata</groupId>
? ? <artifactId>seata-spring-boot-starter</artifactId>
</dependency>
seata:
tx-service-group: csmall_group # 分组
service:
vgroup-mapping:
csmall_group: default # 默认at模式
grouplist:
default: localhost:9090
? ? ? 在需要进行分布式事务的方法上加上?@GlobalTransactional
?注解,比如:
@Service
public class OrderService {
@GlobalTransactional
public void createOrder(Order order) {
// TODO: 创建订单的业务逻辑
// 调用其他微服务的业务逻辑
productService.reduceStock(order.getProductId(), order.getQuantity());
inventoryService.reduceInventory(order.getProductId(), order.getQuantity());
}
}
@GlobalLock
?注解,确保在分布式事务期间不会有并发问题,比如: @Service
public class ProductService {
@GlobalLock
public void reduceStock(Long productId, Integer quantity) {
// TODO: 减少商品库存的业务逻辑
}
}
最后是启动
??
?
?