一,seata 的基本使用
环境搭建:
- 下载 seata:可以从 seata 官网 或者 github 上获取最新版本。
- 启动 seata server:下载 seata 后,配置并启动 seata server,seata 提供了一个默认的 nacos 配置中心,也可以使用其他配置中心。
引入依赖:
- 在微服务应用中,可以通过 maven 或 gradle 引入 seata 的相关依赖。
<dependency> <groupid>io.seata</groupid> <artifactid>seata-spring-boot-starter</artifactid> <version>1.6.1</version> <!-- 根据需要选择最新版本 --> </dependency>
配置 seata
- 在使用全局事务之前,需要确保 seata server 已经启动,并且应用程序的
application.yml
配置正确
seata: tx-service-group: my_test_tx_group # 事务分组 service: vgroup-mapping: my_test_tx_group: default enable-auto-data-source-proxy: true # 自动代理数据源 registry: type: nacos # 注册中心类型 nacos: server-addr: 127.0.0.1:8848 # nacos 地址 namespace: public group: seata_group config: type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: public group: seata_group
在全局事务中使用 @globaltransactional
- 全局事务的控制需要在方法上添加
@globaltransactional
,以确保该方法及其调用的所有子事务受 seata 统一管理。
import io.seata.spring.annotation.globaltransactional; import org.springframework.stereotype.service; import org.springframework.beans.factory.annotation.autowired; @service public class orderservice { @autowired private stockservice stockservice; @autowired private paymentservice paymentservice; @globaltransactional(name = "order-create", rollbackfor = exception.class) public void createorder(string userid, string productid, int amount) { // 扣减库存 stockservice.deductstock(productid, amount); // 处理支付 paymentservice.processpayment(userid, amount); // 插入订单记录 system.out.println("订单创建成功!"); } }
在分支事务中使用 @transactional
- seata 在全局事务中,所有数据库操作会自动成为分支事务。
- 在
stockservice
中:
import org.springframework.stereotype.service; import org.springframework.transaction.annotation.transactional; @service public class stockservice { @transactional public void deductstock(string productid, int amount) { // 执行数据库库存扣减操作 system.out.println("库存扣减成功!"); } }
虽然 stockservice
仍然使用的是本地事务 @transactional
,但因@globaltransactional
处于全局事务上下文中,seata 会自动代理并管理它的事务
二,seata 的工作原理
seata 通过引入 全局事务管理 和 分支事务 来解决分布式系统中的事务一致性问题。
它使用类似于传统数据库事务中的 二阶段提交(2pc,two-phase commit) 协议来确保事务的原子性。
二阶段提交(2pc)过程
seata 采用二阶段提交协议(2pc)来确保分布式事务的一致性。以下是二阶段提交的详细流程:
1. 第一阶段:事务预备(try阶段)
- 全局事务开始:客户端应用向 seata server 发起请求,seata 会生成一个全局事务 id(xid),并返回给客户端应用。全局事务标识用于追踪整个分布式事务。
// 启动全局事务 globaltransaction tx = globaltransactioncontext.getcurrentorcreate(); tx.begin();
- 分支事务注册:每个参与者(微服务)启动后,会向 seata server 注册自己作为一个分支事务,seata server 会为每个分支事务分配一个唯一的事务分支 id(branch id)。
- try 阶段:每个微服务会执行 try 操作,即准备执行本地事务操作,但不提交数据。例如,更新某个数据库中的记录,但不提交。
- 执行数据库操作:每个参与的子事务都会执行数据库更新,但不会真正提交,而是进入
prepare
状态(对于 at 模式,这意味着生成 undo_log)。
2. 第二阶段:提交(commit)或回滚(rollback)
提交(commit):
- seata server 收到全局事务提交请求后,通知所有分支事务提交事务。
- 分支事务提交数据库操作(删除
undo_log
)。
回滚(rollback):
- 如果 seata server 发现某个分支事务执行失败,则通知所有已提交的分支事务回滚,恢复
undo_log
记录的数据。
三,seata 的四种事务模式
1. at 模式(自动事务模式)
at(auto transaction)模式是 seata 中最常用的分布式事务模式,适用于对数据库执行常规的 crud(增、删、改、查)操作的场景,尤其是简单的 sql 操作。
特点:
- 自动化:at 模式在数据库的每个操作上都自动代理,开发者无需显式地编写事务的提交和回滚操作。seata 会自动插入 undo 日志,在事务回滚时自动恢复数据库的原始状态。
- 无须业务代码改动:at 模式的关键优势是,开发者无需修改现有的业务代码。通过 seata 自动管理事务,开发者只需确保数据库支持 undo 日志(例如 mysql、oracle 等)。
- 仅适用于数据库操作:at 模式适用于标准的数据库操作,它依赖于数据库的日志和 undo 日志机制。
工作原理:
- try 阶段:seata 会拦截数据库的更新操作,并记录 undo 日志,但不立即提交。此时,数据库的数据并未真正修改,而是保留了“回滚”的信息。
- commit 阶段:当全局事务提交时,seata 会通过协调所有分支事务,最终确认提交所有的数据修改。
- rollback 阶段:如果全局事务失败,则会通过回滚所有分支事务的操作,恢复数据。
适用场景:
- 适用于大多数微服务场景,尤其是直接依赖数据库操作的业务逻辑,seata 会自动进行事务控制。
2. tcc 模式(try-confirm-cancel)
tcc(try-confirm-cancel)模式是一种基于补偿的分布式事务模式,它适用于业务操作较为复杂、涉及多个服务的场景。与 at 模式的自动提交和回滚不同,tcc 模式要求开发者显式地实现 try、confirm 和 cancel 这三个阶段。
特点:
- 精确控制:开发者需要编写 try、confirm 和 cancel 方法,能够精确控制每个阶段的事务操作。
- 高灵活性:tcc 模式适用于复杂的业务操作,尤其是那些需要进行资源锁定、状态更新、外部系统调用的场景。
- 手动补偿:tcc 模式的关键是补偿机制,若某个操作失败,需要通过 cancel 操作来撤销之前的资源占用或状态变更。
工作原理:
- try 阶段:执行实际的业务操作,但不会提交(例如,锁定资源、预扣资金)。此时,操作是幂等的,并且不改变系统状态。
- confirm 阶段:如果 try 阶段成功,confirm 阶段会提交操作,确认业务操作完成(例如,实际扣款、最终更新库存)。
- cancel 阶段:如果 try 阶段失败或某个分支事务失败,则执行 cancel 操作,撤销之前的操作(例如,解锁资源、退款)。
适用场景:
- 长时间执行的业务:例如支付、库存扣减等复杂的跨服务操作,需要实现显式的补偿机制。
- 必须确保操作的最终一致性:tcc 能够处理在服务之间的协作,并确保每个服务能明确知道何时提交或回滚事务。
3. saga 模式
saga(长事务模式)是一个分布式事务处理模式,适用于跨多个微服务的长事务。与 tcc 模式不同,saga 模式通过将长事务拆分成多个小事务来保证一致性,每个小事务都会有一个补偿事务(compensating transaction),用于回滚操作。
特点:
- 长事务拆分:将大事务拆分为一系列小事务,每个小事务都可以独立提交或回滚。
- 补偿机制:每个小事务都需要实现一个补偿事务,当某个事务失败时,通过补偿事务来撤销之前的操作。
- 可以异步执行:每个子事务之间可以独立执行,并且可以异步执行,不需要像 tcc 那样锁定资源。
工作原理:
- 子事务:将全局事务拆分为多个子事务,每个子事务执行独立的操作(例如,支付、库存扣减等)。
- 补偿操作:每个子事务都有相应的补偿操作。如果某个子事务失败,执行补偿操作撤销之前的操作。
- 全局事务结束:当所有子事务都执行成功时,结束整个 saga 事务;如果某个子事务失败,则根据补偿规则进行回滚。
适用场景:
- 长时间的、跨多个服务的事务:例如订单的创建、支付、发货等操作。
- 能够容忍部分失败的场景:saga 模式适用于业务流程中的某些操作失败后,可以通过补偿机制修复的场景。
4. xa 模式(原生分布式事务)
xa 模式是传统的分布式事务协议,它基于 xa协议,是一种强一致性的分布式事务模式。seata 的 xa 模式要求参与者支持 xa 事务协议,例如数据库、消息队列等。
特点:
- 强一致性:xa 模式是最严格的分布式事务协议,确保所有分布式事务的最终一致性。
- 两阶段提交协议(2pc):与 at 模式类似,xa 模式也采用了 2pc 协议来管理事务一致性。
- 依赖于底层数据库的支持:必须使用支持 xa 事务的数据库(例如,mysql、oracle 等)。
工作原理:
- 第一阶段(prepare):所有参与者准备提交事务,但不提交。
- 第二阶段(commit/rollback):如果所有参与者都准备好,则提交事务,否则回滚事务。
适用场景:
- 严格要求强一致性的场景:例如银行转账等对事务一致性要求极高的业务。
总结
seata 支持以下四种分布式事务模式:
- at 模式:适用于标准的数据库操作,自动管理事务,适合不涉及复杂业务逻辑的场景。
- tcc 模式:适用于跨多个服务的复杂业务,需要手动编写补偿逻辑。
- saga 模式:适用于长事务,适合拆分为多个子事务的场景,每个子事务都可以独立回滚。
- xa 模式:严格一致性的分布式事务协议,适用于需要强一致性的场景,如金融交易等。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论