阿里分布式事务seata
admin
2024-03-14 12:45:37
0

(一) seata 介绍

  • Seata 是一款阿里开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案
  • 这里演示学习使用SpringCloud/SpringBoot集成配置了Seata,并使用AT模式实现分布式事务回滚
  • Seata GitHub
  • Seata 官方文档
  • Seata Demo GitHub

(二) Seata server 安装配置

环境准备

  • Mac OS
  • Mysql8
  • Eureka注册中心

GitHub 下载v1.1.0 Seata v1.1.0

  • unzip seata-server-1.1.0.zip
  • cd /seata/conf
  • 由于seatev1.1.0默认驱动是mysql5,在seata/lib目录下,将mysql-connector-java-8.0.19.jar版本的jar包替换原来的mysq5;修改file.conf中的driverClassName = “com.mysql.cj.jdbc.Driver”
  • 修改file.conf如下;修改为db模式,并且配置自己的mysql数据库链接;注意service配置中的vgroupMapping.licaibo_tx_group,其中licaibo_tx_group为自己定义,到时SpringBoot集成seata的时候需要保持一致
## transaction log store, only used in seata-server
store {## store mode: file、dbmode = "db"## file store propertyfile {## store location dirdir = "sessionStore"# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptionsmaxBranchSessionSize = 16384# globe session size , if exceeded throws exceptionsmaxGlobalSessionSize = 512# file buffer size , if exceeded allocate new bufferfileWriteBufferCacheSize = 16384# when recover batch read sizesessionReloadReadSize = 100# async, syncflushDiskMode = async}## database store propertydb {## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.datasource = "dbcp"## mysql/oracle/h2/oceanbase etc.dbType = "mysql"driverClassName = "com.mysql.cj.jdbc.Driver"url = "jdbc:mysql://localhost:3306/seat-server"user = "root"password = "root"minConn = 1maxConn = 10globalTable = "global_table"branchTable = "branch_table"lockTable = "lock_table"queryLimit = 100}service {#transaction service group mappingvgroupMapping.licaibo_tx_group = "default"#only support when registry.type=file, please don't set multiple addressesdefault.grouplist = "127.0.0.1:8091"#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false
}}

在自己的seat-server数据库需要创建三张表,具体脚本在 Seata-mysql-script

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(`xid`                       VARCHAR(128) NOT NULL,`transaction_id`            BIGINT,`status`                    TINYINT      NOT NULL,`application_id`            VARCHAR(32),`transaction_service_group` VARCHAR(32),`transaction_name`          VARCHAR(128),`timeout`                   INT,`begin_time`                BIGINT,`application_data`          VARCHAR(2000),`gmt_create`                DATETIME,`gmt_modified`              DATETIME,PRIMARY KEY (`xid`),KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8;-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(`branch_id`         BIGINT       NOT NULL,`xid`               VARCHAR(128) NOT NULL,`transaction_id`    BIGINT,`resource_group_id` VARCHAR(32),`resource_id`       VARCHAR(256),`branch_type`       VARCHAR(8),`status`            TINYINT,`client_id`         VARCHAR(64),`application_data`  VARCHAR(2000),`gmt_create`        DATETIME(6),`gmt_modified`      DATETIME(6),PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8;-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(`row_key`        VARCHAR(128) NOT NULL,`xid`            VARCHAR(96),`transaction_id` BIGINT,`branch_id`      BIGINT       NOT NULL,`resource_id`    VARCHAR(256),`table_name`     VARCHAR(32),`pk`             VARCHAR(36),`gmt_create`     DATETIME,`gmt_modified`   DATETIME,PRIMARY KEY (`row_key`),KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8;

修改registry.conf,配置注册的Eureka注册中心

registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "eureka"nacos {serverAddr = "localhost"namespace = ""cluster = "default"}eureka {serviceUrl = "http://localhost:9001/eureka"application = "default"weight = "1"}redis {serverAddr = "localhost:6379"db = "0"}zk {cluster = "default"serverAddr = "127.0.0.1:2181"session.timeout = 6000connect.timeout = 2000}consul {cluster = "default"serverAddr = "127.0.0.1:8500"}etcd3 {cluster = "default"serverAddr = "http://localhost:2379"}sofa {serverAddr = "127.0.0.1:9603"application = "default"region = "DEFAULT_ZONE"datacenter = "DefaultDataCenter"cluster = "default"group = "SEATA_GROUP"addressWaitTime = "3000"}file {name = "file.conf"}
}config {# file、nacos 、apollo、zk、consul、etcd3type = "file"nacos {serverAddr = "localhost"namespace = ""group = "SEATA_GROUP"}consul {serverAddr = "127.0.0.1:8500"}apollo {app.id = "seata-server"apollo.meta = "http://192.168.1.204:8801"namespace = "application"}zk {serverAddr = "127.0.0.1:2181"session.timeout = 6000connect.timeout = 2000}etcd3 {serverAddr = "http://localhost:2379"}file {name = "file.conf"}
}

(三) SpringBoot/SpringClod集成Seata

在各个微服务的SpringBoot增加依赖

        com.alibaba.cloudspring-cloud-alibaba-seata2.1.0.RELEASEseata-allio.seataio.seataseata-all1.1.0

在每个微服务的数据库创建undo_log,用于执行回滚记录;具体脚本在 Seata-mysql-script

-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(`id`            BIGINT(20)   NOT NULL AUTO_INCREMENT COMMENT 'increment id',`branch_id`     BIGINT(20)   NOT NULL COMMENT 'branch transaction id',`xid`           VARCHAR(100) NOT NULL COMMENT 'global transaction id',`context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',`rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',`log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',`log_created`   DATETIME     NOT NULL COMMENT 'create datetime',`log_modified`  DATETIME     NOT NULL COMMENT 'modify datetime',PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDBAUTO_INCREMENT = 1DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';

resources目录下增加file.conf和registry.conf两个配置文件

  • SpringBoot配置file.conf;注意service中的vgroupMapping.licaibo_tx_group,其中licaibo_tx_group和seata server的配置保持一致
           transport {# tcp udt unix-domain-sockettype = "TCP"#NIO NATIVEserver = "NIO"#enable heartbeatheartbeat = true# the client batch send request enableenableClientBatchSendRequest = true#thread factory for nettythreadFactory {bossThreadPrefix = "NettyBoss"workerThreadPrefix = "NettyServerNIOWorker"serverExecutorThread-prefix = "NettyServerBizHandler"shareBossWorker = falseclientSelectorThreadPrefix = "NettyClientSelector"clientSelectorThreadSize = 1clientWorkerThreadPrefix = "NettyClientWorkerThread"# netty boss thread size,will not be used for UDTbossThreadSize = 1#auto default pin or 8workerThreadSize = "default"}shutdown {# when destroy server, wait secondswait = 3}serialization = "seata"compressor = "none"}service {#transaction service group mappingvgroupMapping.licaibo_tx_group = "default"#only support when registry.type=file, please don't set multiple addressesdefault.grouplist = "127.0.0.1:8091"#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false}client {rm {asyncCommitBufferLimit = 10000lock {retryInterval = 10retryTimes = 30retryPolicyBranchRollbackOnConflict = true}reportRetryCount = 5tableMetaCheckEnable = falsereportSuccessEnable = false}tm {commitRetryCount = 5rollbackRetryCount = 5}undo {dataValidation = truelogSerialization = "jackson"logTable = "undo_log"}log {exceptionRate = 100}}

SpringBoot配置registry.conf

      registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "eureka"nacos {serverAddr = "localhost"namespace = ""cluster = "default"}eureka {serviceUrl = "http://localhost:9001/eureka"application = "default"weight = "1"}redis {serverAddr = "localhost:6379"db = "0"}zk {cluster = "default"serverAddr = "127.0.0.1:2181"session.timeout = 6000connect.timeout = 2000}consul {cluster = "default"serverAddr = "127.0.0.1:8500"}etcd3 {cluster = "default"serverAddr = "http://localhost:2379"}sofa {serverAddr = "127.0.0.1:9603"application = "default"region = "DEFAULT_ZONE"datacenter = "DefaultDataCenter"cluster = "default"group = "SEATA_GROUP"addressWaitTime = "3000"}file {name = "file.conf"}}config {# file、nacos 、apollo、zk、consul、etcd3type = "file"nacos {serverAddr = "localhost"namespace = ""group = "SEATA_GROUP"}consul {serverAddr = "127.0.0.1:8500"}apollo {app.id = "seata-server"apollo.meta = "http://192.168.1.204:8801"namespace = "application"}zk {serverAddr = "127.0.0.1:2181"session.timeout = 6000connect.timeout = 2000}etcd3 {serverAddr = "http://localhost:2379"}file {name = "file.conf"}}

配置SpringBoot工程的application.yml

spring:cloud:alibaba:seata:tx-service-group: licaibo_tx_group    

创建数据源代理

/*** 数据源代理* @author wangzhongxiang*/
@Configuration
public class DataSourceConfiguration {@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource druidDataSource(){DruidDataSource druidDataSource = new DruidDataSource();return druidDataSource;}@Primary@Bean("dataSource")public DataSourceProxy dataSource(DataSource druidDataSource){return new DataSourceProxy(druidDataSource);}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy)throws Exception{SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/*.xml"));sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());return sqlSessionFactoryBean.getObject();}}  

(四) 启动测试

  • 启动Eureka注册中心
  • 启动seata ./seata-server.sh
  • 启动集成好的参与分布式事务的SpringBoot工程
  • 在服务的入口使用@GlobalTransactional(name = “xxx”,rollbackFor = Exception.class)开启分布式事务
  • 本文是参考阿里的demo,这里使用的是 springcloud-eureka-feign-mybatis-seata

(五) 更多集成方式例子

  • seata v1.1.0提供了seata-spring-boot-starte,是使用springboot自动装配来简化seata-all的复杂配置。1.0.0可用于替换seata-all
  • 配置上则不需要registry.conf和file.conf文件,将配置信息写在application.yml
  • 具体参考阿里demo seata-spring-boot-starter-samples

相关内容

热门资讯

有什么搞笑好看的鬼片? 有什么搞笑好看的鬼片?韩国片主君的太阳!
摘橘子沈从文中夭夭是一个什么样... 摘橘子沈从文中夭夭是一个什么样的女孩摘橘子沈从文中夭夭是一个什么样的女孩?相关内容如下:夭夭是《边城...
作文题目:童心荟萃.主题;节水... 作文题目:童心荟萃.主题;节水。爱水。护水~~╮(╯▽╰)╭ ...
我可不可以和姐夫家的堂兄弟结婚... 我可不可以和姐夫家的堂兄弟结婚?这个是没问题的,不是三代内有血亲关系的都可以
原生家庭对人的影响很大,如何摆... 原生家庭对人的影响很大,如何摆脱原生家庭所造成的性格缺陷?在学校里好好学习,尽量不要被原生家庭的坏习...
你知道哪些珍惜时间的名人故事吗... 你知道哪些珍惜时间的名人故事吗?1、悬梁刺股东汉时候,有个人名叫孙敬,是著名的政治家。他年轻时勤奋好...
有一首歌,歌词里铿锵玫瑰,作何... 有一首歌,歌词里铿锵玫瑰,作何解释?铿 锵 玫 瑰"铿锵"意味着声音宏亮,节奏分明;"玫瑰"代表着美...
“我越爱越深越迷茫,你怎么舍得... “我越爱越深越迷茫,你怎么舍得我心伤,说好一辈子不忘”是什么歌?您好啊!这是一首经典的歌曲---《模...
谁有我们小学时候的课文《八角楼... 谁有我们小学时候的课文《八角楼上的灯光》?《八角楼上的灯光》 回忆起来 上那课的时候宁...
读《从百草园到三味书屋》,谈…... 读《从百草园到三味书屋》,谈……三味书屋的读书生活哪些地方应该改革?至少三方面!教学思想,教学方法,...
腾格里沙漠、巴丹吉林沙漠、库布... 腾格里沙漠、巴丹吉林沙漠、库布齐沙漠哪个更好玩更美?巴丹吉林沙漠腾格里沙漠、巴丹吉林林沙漠、库布齐沙...
AI能回到76人吗 AI能回到76人吗希望AI能回到梦开始的地方 拿下冠军不能 他可能去一只有夺冠实力的球队
她说民谣太穷, 一听就是一根烟... 她说民谣太穷, 一听就是一根烟, 一听就是三瓶酒, 而我只有一根烟了, 还要撑一夜。是什么意思 故...
老井蛙的遗言来自哪则寓言故事 老井蛙的遗言来自哪则寓言故事老井蛙的遗言 在病榻上躺了三个月光景的老井蛙,觉得自己的日子已经不多了,...
《斗罗大陆》中,有哪些震撼人心... 《斗罗大陆》中,有哪些震撼人心的魂技呢?唐三的第五魂技:蓝银霸王枪。一点寒芒先到 随后枪出如龙。在对...
除了《寻梦环游记》,还有这5套... 除了《寻梦环游记》,还有这5套暖心绘本教孩子看待死亡!清明节到了,扫墓、祭祖的同时,死亡这个话题不可...
海南为游客提供热带雨林游玩多元... ■ 海南日报全媒体记者 刘宁玥住进海南热带雨林是怎样的体验?7月6日,住进保亭黎族苗族自治县七仙岭温...
蓝桉已遇释槐鸟是什么意思 梗来... 蓝桉已遇释槐鸟是什么意思 梗来源全诗分享最近“蓝桉遇释槐鸟”在网络社交平台十分流行,很多人都在说这句...
一家三口去张家界五日四晚跟团游... 一家三口去张家界五日四晚跟团游价格,张家界纯玩五日游报团多少钱,看完不踩坑。最近我和家人终于决定出发...
贵州黔西南自驾|营地纳山水,风... 摘自《汽车自驾游》杂志2025年7月刊 分享嘉宾_ 敖美丽(贵州贞丰三岔河国际露营基地 主理人) 贵...