Seata是什么?
官网解释:Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
用咱们理解的说,seata就是处理分布式事务使用的。
1、seate的设计初衷
(1)业务无侵入:引入分布式事务,不能影响业务。比如,tcc着这种人工补偿是不行的。(虽然seate也有补偿,但是是不需要人工干预的)
(2)高性能:不能拖慢业务。比如xa机制,只有等到所有事务都执行完了,才释放锁,严重影响事务。(曾经用过lcn,这个东西就是二阶段提交,但是spring boot 2支持的很不好,最后放弃)
高性能方面,体现在本地事务执行完,就commit释放锁。但是,如果都是seata事务,还是持有全局锁,一旦发生异常,是可以进行数据回滚的,所以整体来讲是安全的。
2、 已有的分布式事务方案
xa: 单服务多数据库事务,好做,多服务,则tc要抽出来,性能各方面,各种不好做。
tcc:手写补偿业务,不妥。
基于消息中间件的最终一致性:异常回滚方面先捕获,通用性不好,而且特别麻烦。
3、 理想的分布式事务
能够像本地事务一样,解决分布式事务问题,通过一个注解transaction注解,就能搞定。
lcn也能入本地事务一样搞定分布式事务,但是这个东西,性能不好,而且各种问题,更可恶的是,spring boot2根本无法完。(现在不知道LCN还在更新么,整体更新速度慢,个人更新)
整体执行流程如下:
seate官网下载地址:https://github.com/seata/seata/releases
开始配置seata
一、创建数据库和表
https://github.com/seata/seata/tree/1.3.0/script/server/db/mysql.sql
创建三张表:global_table、branch_table、lock_table
二、配置seata服务器配置
1、通过配置file.conf文件,达到seata的本地配置
(1)配置使用数据库
启动包: seata-->conf-->file.conf,修改store.mode="db或者redis"
源码: 根目录-->seata-server-->resources-->file.conf,修改store.mode="db或者redis"
(2)配置数据库链接地址
在file.conf中改成自己的链接地址即可,要8.0的数据库,数据库驱动要com.mysql.cj.jdbc.Driver
(3)配置注册中心registry.conf
就改下面标红的就可以了,其它都不需要改
(3)改日志文件,方便管理日志
打开conf下的logback.xml,改下路径就可以,在seata下创建一个logs目录,把路径指定过来就好
(5)启动seata看看,如果不报错,并且nacos中seata注册成功,一切OK
3、结合项目使用seata
在每个业务数据库种创建undo_log表,undo_log是回滚记录表,这个表需要建在业务库中,几个业务库就需要有几张这样的日志表
sql地址:Seata 快速开始
创建项目,第一步导入依赖,
注意:
这里的boot依赖必须用2.3.2版本
alibabaCloud必须用2.2.1版本
否则seata起不来
①父项目依赖
parent> oupId>org.springframework.boot tifactId>spring-boot-starter-parentfactId> rsion>2.3.2.RELEASE lativePath/> !-- lookup parent from repository --> /parent> dependencyManagement> pendencies> dependency> roupId>com.alibaba.cloud rtifactId>spring-cloud-alibaba-dependenciesifactId> ersion>2.2.1.RELEASE ype>pom cope>import /dependency> ependencies> /dependencyManagement> |
②子项目的依赖
com.alibaba.cloudgroupId> Id>spring-cloud-starter-alibaba-seatatId> ns> usion> groupId>io.seataroupId> artifactId>seata-spring-boot-starterId> lusion> ons> io.seataoupId> Id>seata-spring-boot-starter 1.3.0on> |
在TM和RM方配置文件中加入以下配置
seata: application-id: ${spring.application.name} enabled: true tx-service-group: my_test_tx_group 这是群组名,跟config.txt中service.vgroupMapping.点后面的一致,这个名字可以根据每个rm起个名字,也可以都用一个名字,按照规范来讲是每个业务项目一个名字为好 config: type: nacos nacos: namespace: 043fc32b-f2d2-4084-bcec-92345cf35f97 server-addr: localhost:8848 group: SEATA_GROUP username: nacos password: nacos registry: type: nacos nacos: application: seata-server namespace: 043fc32b-f2d2-4084-bcec-92345cf35f97 server-addr: localhost:8848 group: SEATA_GROUP username: nacos password: nacos |
TM方法上加注解:
@RequestMapping("save") @GlobalTransactional public String save(){ userFeign.test(); stockFeign.test(); return "ok"; } |
RM的被调用方法上都需要加@Transactional注解
分支事务如何提交和回滚?
seata对jdbc做了一个代理,会分析sql,然后生成, 这条记录修改前后的镜像(也就是一个json),然后保存在事务所在数据库undo_log表中(所以每个服务都需要一张这个表)。如此,当回滚的时候,取出这个镜像,解析成反向sql,执行就完了。
所以这里的关键点在于:他能分析sql,然后解析出反向sql。也就省去了,手写补偿业务的问题。