文章目录
- 分布式事务
- Seata简介
- Seata分布式事务处理过程
- 1. seata server的安装和配置
- 2. seata client 配置
-
- 建undo_log表
- 依赖
- yaml配置
- 3. Nacos配置中心添加seata的配置
- 开启分布式事务功能
- Q&A
- 参考
- 本文使用的nacos版本1.4.2,seata版本1.4.2。seata从v1.4.2版本开始,已支持从一个Nacos dataId中获取所有配置信息,只需要额外添加一个dataId配置项,低版本的配置要多一点,所以建议还是使用本文的版本
- 本文只包含seata的安装和配置,不包含具体业务代码
分布式事务
- 一次业务操作需要跨多个数据源或需要跨多个微服务进行RPC,就需要引入分布式事务,保证不同节点之间的数据一致性。
- 分布式事务的实现有很多种,最具有代表性的是由 Oracle Tuxedo 系统提出的 XA 分布式事务协议。它包含两阶段提交(2PC)和三阶段提交(3PC)两种实现
- 其他的还有:
- MQ 事务:利用消息中间件来异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像 XA 协议那样的性能问题。
- TCC 事务:是 Try、Commit、Cancel 三种指令的缩写,其逻辑模式类似于 XA 两阶段提交,但是实现方式是在代码层面来人为实现。
Seata简介
- Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了
AT、TCC、SAGA
和XA
事务模式,为用户打造一站式的分布式解决方案。 - 核心概念:一个 ID + 三个组件
- Transaction ID XID :全局唯一的事务ID
- Transaction Coordinator(TC) :事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚
- Transaction Manager? :控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议
- Resource Manager(RM) :控制分支事务,负责分支注册,状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚
- 传统 2PC 的问题在 Seata 中得到了解决,它通过对本地关系数据库的分支事务的协调来驱动完成全局事务,是工作在应用层的中间件。主要优点是性能较好,且不长时间占用连接资源,它以高效并且对业务 0 侵入的方式解决微服务场景下面临的分布式事务问题
- Seata实现2PC与传统2PC的差别
- 架构层次方面:传统 2PC 方案的 RM 实际上是在数据库层,RM 本质上就是数据库自身,通过 XA 协议实现,而 Seata 的 RM 是以 jar 包的形式作为中间件层部署在应用程序这一侧的
- 两阶段提交方面:传统 2PC无论第二阶段的决议是 commit 还是 rollback ,事务性资源的锁都要保持到 Phase2 完成才释放。而 Seata 的做法是在 Phase1 就将本地事务提交,这样就可以省去 Phase2 持锁的时间,整体提高效率。
Seata分布式事务处理过程
- TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID
- XID在微服务调用链路的上下文中传播
- RM向TC注册分支事务,将其纳入XID对应全局事务的管辖
- TM向TC发起针对XID的全局提交或回滚决议;
- TC调度XID下管辖的全部分支事务完成提交或回滚请求。
1. seata server的安装和配置
- 去官网下载1.4.2版本,解压即可(解压后可以阅读一下readme文件,了解server、client、config-center的区别)
- 修改conf目录下的file.conf、registry.conf文件,这个简单,参考这篇文章的相关内容,其他部分就不要看了
- 还需要创建seata数据库,执行官网提供的sql脚本即可
2. seata client 配置
建undo_log表
- 在涉及到分布式事务的业务数据库中创建一个
undo_log
表,只需执行官网提供的sql脚本 - 注意每个相关数据库都要建这个表,不是只建一个
依赖
- 对于依赖的说明,参考官网
<!--nacos-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--seata-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><!--<version>2.2.1.RELEASE</version>--> <!--没有父pom就在这里指定版本--><exclusions><!--seata 排除自带的seata-spring-boot-starter--><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.4.2</version>
</dependency>
- 父pom中的spring cloud alibaba版本为2.2.1.RELEASE
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.2.1.RELEASE</version><type>pom</type><scope>import</scope>
</dependency>
yaml配置
server:port: 2001spring:application:name: seata-order-servicecloud:nacos:discovery:server-addr: localhost:8848datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_orderusername: rootpassword: root
feign:hystrix:enabled: false
seata:enabled: trueenable-auto-data-source-proxy: true #是否开启数据源自动代理,默认为truetx-service-group: default_tx_group #对应seataServer.properties中的service.vgroupMapping.default_tx_group 集群分组registry:type: nacos #注册中心类型:nacosnacos:application: seata-server # seata-server注册在nacos中的服务名server-addr: 127.0.0.1:8848 # nacos的地址端口group : SEATA_GROUP # seata-server在nacos的分组namespace: "" # seata-server在nacos的命名空间ID,默认是public,可以不填username: nacos # nacos账号password: nacos # nacos密码config:type: nacosnacos:server-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace: "" # seata-server的配置文件的命名空间IDdataId: seataServer.properties # seata-server在nacos的配置dataIdusername: nacospassword: nacoslogging:level:io:seata: infomybatis:mapperLocations: classpath:mapper/*.xml
3. Nacos配置中心添加seata的配置
seata配置添加到nacos后,各个client端就只需从nacos获取配置了
- 需要一个config.txt文件,如何获取,参考官方文档-Nacos 配置中心
- 然后需要修改config.txt文件的内容,一般就改store.mode,相应mode的配置当然也要改了
- 注意不需要再执行nacos-config.sh脚本,直接在nacos配置管理中新建一个配置文件,配置内容就是config.txt的内容,格式为properties,如下图:
- 完成后,启动seata即可
开启分布式事务功能
- 需要进行事务的方法上添加
@GlobalTransactional
(name = “唯一即可”, rollbackFor = Exception.class) - 成功了吗?开不开心?
Q&A
- 启动微服务时,如果遇到报错:
can not get cluster name in registry config ‘XXX‘, please make sure registry config correct
,可以重启nacos和Seata试一试
参考
- 官网新手部署指南
- SpringCloud-2.0-周阳(24. 分布式事务 - Seata)学习笔记
- 分布式事务有这一篇就够了!