SpringBoot+Seata在多数据源和feign中的简单使用
SpringBoot+Seata简单使用
目录
- seata执行过程
- 安装seata
- 下载seata
- 使用自定义配置文件,NACOS为注册中心
- 结合springboot实现AT模式
- 1.多数据源
- 引入依赖
- bootstrap.yml配置
- 在使用的方法上用@GlobalTransactional注解
- 调用接口正常时
- 调用接口报错时回滚
- 2.配合feign
- seata优缺点
seata执行过程

(官网的图)
安装seata
seata官网安装教程
下载seata
我选择了用docker下载选择1.6.1最新的版本,docker-compose启动,有个注意的细节,官网说明了

docker pull seataio/seata-server:1.6.1

使用自定义配置文件,NACOS为注册中心
先启动一次把application.yml配置文件放在宿主机中,(注意1.4.2之前是file.conf,配置写法也不相同)
docker run -d -p 8091:8091 -p 7091:7091 --name seata-serve seataio/seata-server:1.6.1
docker cp seata-serve:/seata-server/resources /home/seata/config
拷出后可以,可以选择修改application.yml再cp进容器,或者rm临时容器,如下重新创建,并做好映射路径设置,我选择了删除旧镜像使用docker-compose启动新的镜像。
找到/home/seata/config/resources/application.yml,修改对应的配置,详细配置文件里面有个 application.example.yml可以参考或者上官网查看

application.yml
server:port: 7091 #界面管理端口spring:application:name: seata-server #应用名称logging:config: classpath:logback-spring.xmlfile:path: ${user.home}/logs/seataextend:logstash-appender:destination: 127.0.0.1:4560kafka-appender:bootstrap-servers: 127.0.0.1:9092topic: logback_to_logstashconsole:user:username: seata #账号password: seata #密码seata:config:# support: nacos, consul, apollo, zk, etcd3 #支持的数据存储类型type: nacos #选择的数据类型为nacosnacos:server-addr: nacosIP:8848 #nacos地址namespace: seata #nacos命名空间group: SEATA_GROUP #组名usernam: nacos #账号password: xxx #密码data-id: seataServer.properties #读取的配置文件,官网有registry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: nacosIP:8848group: SEATA_GROUPnamespace: seata# tc集群名称cluster: defaultusername: nacospassword: xxx #密码# store:# support: file 、 db 、 redis# mode: file# server:# service-port: 8091 #If not configured, the default is '${server.port} + 1000'security:secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017tokenValidityInMilliseconds: 1800000ignore:urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
dcoker-compose
version: "3"
services:seata-server:image: seataio/seata-server:1.6.1 #镜像container_name: my-seata #容器名称ports:- "8091:8091"- "7091:7091"environment:#一定要指定store_mode,因为application.yml没指定,如application.yml指定了这可以不指定。如无指定会出现全局数据开启失败的问题- STORE_MODE=db #指定为数据库,配置文件写在nacos# 以SEATA_IP作为host注册seata server- SEATA_IP=xx.xx.xx.xx #该IP一定是要服务能访问到的地址- SEATA_PORT=8091 #服务端口 volumes:- "/home/seata/config/resources:/seata-server/resources"- "/usr/share/zoneinfo/Asia/Shanghai:/etc/localtime" #设置系统时区- "/usr/share/zoneinfo/Asia/Shanghai:/etc/timezone" #设置时区
nacos上的配置文件seataServer.properties,配置文件官方有官方配置

store.mode=db
#-----db-----
store.db.datasource=druid
store.db.dbType=mysql #指定数据库类型
# 需要根据mysql的版本调整driverClassName
# mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
# mysql8以下版本的driver:com.mysql.jdbc.Driver
store.db.driverClassName=com.mysql.cj.jdbc.Driver #在数据库执行select version()查看版本;
store.db.url=jdbc:mysql://xx.xx.xx.xx:3306/seata-server?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
store.db.user= root
store.db.password=root
# 数据库初始连接数
store.db.minConn=1
# 数据库最大连接数
store.db.maxConn=20
# 获取连接时最大等待时间 默认5000,单位毫秒
store.db.maxWait=5000
# 全局事务表名 默认global_table
store.db.globalTable=global_table
# 分支事务表名 默认branch_table
store.db.branchTable=branch_table
# 全局锁表名 默认lock_table
store.db.lockTable=lock_table
# 查询全局事务一次的最大条数 默认100
store.db.queryLimit=100# undo保留天数 默认7天,log_status=1(附录3)和未正常清理的undo
server.undo.logSaveDays=7
# undo清理线程间隔时间 默认86400000,单位毫秒
server.undo.logDeletePeriod=86400000
# 二阶段提交重试超时时长 单位ms,s,m,h,d,对应毫秒,秒,分,小时,天,默认毫秒。默认值-1表示无限重试
# 公式: timeout>=now-globalTransactionBeginTime,true表示超时则不再重试
# 注: 达到超时时间后将不会做任何重试,有数据不一致风险,除非业务自行可校准数据,否者慎用
server.maxCommitRetryTimeout=-1
# 二阶段回滚重试超时时长
server.maxRollbackRetryTimeout=-1
# 二阶段提交未完成状态全局事务重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.committingRetryPeriod=1000
# 二阶段异步提交状态重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.asynCommittingRetryPeriod=1000
# 二阶段回滚状态重试回滚线程间隔时间 默认1000,单位毫秒
server.recovery.rollbackingRetryPeriod=1000
# 超时状态检测重试线程间隔时间 默认1000,单位毫秒,检测出超时将全局事务置入回滚会话管理器
server.recovery.timeoutRetryPeriod=1000
在seata使用的数据库上建立这几张表,官方有sql

CREATE TABLE `branch_table` (`branch_id` bigint NOT NULL,`xid` varchar(128) NOT NULL,`transaction_id` bigint DEFAULT NULL,`resource_group_id` varchar(32) DEFAULT NULL,`resource_id` varchar(256) DEFAULT NULL,`branch_type` varchar(8) DEFAULT NULL,`status` tinyint DEFAULT NULL,`client_id` varchar(64) DEFAULT NULL,`application_data` varchar(2000) DEFAULT NULL,`gmt_create` datetime(6) DEFAULT NULL,`gmt_modified` datetime(6) DEFAULT NULL,PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `distributed_lock` (`lock_key` char(20) NOT NULL,`lock_value` varchar(20) NOT NULL,`expire` bigint DEFAULT NULL,PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `global_table` (`xid` varchar(128) NOT NULL,`transaction_id` bigint DEFAULT NULL,`status` tinyint NOT NULL,`application_id` varchar(32) DEFAULT NULL,`transaction_service_group` varchar(32) DEFAULT NULL,`transaction_name` varchar(128) DEFAULT NULL,`timeout` int DEFAULT NULL,`begin_time` bigint DEFAULT NULL,`application_data` varchar(2000) DEFAULT NULL,`gmt_create` datetime DEFAULT NULL,`gmt_modified` datetime DEFAULT NULL,PRIMARY KEY (`xid`),KEY `idx_status_gmt_modified` (`status`,`gmt_modified`),KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;CREATE TABLE `lock_table` (`row_key` varchar(128) NOT NULL,`xid` varchar(128) DEFAULT NULL,`transaction_id` bigint DEFAULT NULL,`branch_id` bigint NOT NULL,`resource_id` varchar(256) DEFAULT NULL,`table_name` varchar(32) DEFAULT NULL,`pk` varchar(36) DEFAULT NULL,`status` tinyint NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',`gmt_create` datetime DEFAULT NULL,`gmt_modified` datetime DEFAULT NULL,PRIMARY KEY (`row_key`),KEY `idx_status` (`status`),KEY `idx_branch_id` (`branch_id`),KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
AT模式还要在对应的业务库加上undo_log表
CREATE TABLE `undo_log` (`id` bigint NOT NULL AUTO_INCREMENT,`branch_id` bigint NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb3;
docker-compose up -d 后台启动seata
docker logs -f seata-server 查看执行日志
nacos上看到seata服务

IP:7091能登陆seata管理界面

结合springboot实现AT模式
1.多数据源
引入依赖
<!--多数据源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId></dependency><!--seata--><dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.2</version></dependency>
bootstrap.yml配置
seata:enabled: true #开启enable-auto-data-source-proxy: false #关闭数据源代理,这里不关闭会出现事务回滚问题,具体可以查看application-id: ${spring.application.name} # Seata 应用编号,默认为 ${spring.application.name}tx-service-group: mytest-group # Seata 事务组编号,用于 TC 集群名registry:type: nacosnacos:application: seata-serverserver-addr: xx.xx.xx.xx:8848namespace: 332a6313-c96c-4c5d-b3b5-3063093bf8f9group: SEATA_GROUPconfig:type: nacosnacos:server-addr: xx.xx.xx.xx:8848namespace: 332a6313-c96c-4c5d-b3b5-3063093bf8f9group: SEATA_GROUP# 服务配置项,对应 ServiceProperties 类service:# 虚拟组和分组的映射vgroup-mapping:multi-datasource-service-group: default# 分组和 Seata 服务的映射grouplist:default: xx.xx.xx.xx:8091 #seata服务地址

(图片来源网络)
在使用的方法上用@GlobalTransactional注解


调用接口正常时


数据能正常拆入2个表中

调用接口报错时回滚
调用前,远程服务器的remotest表无数据

执行全局事务,TM申请了XID


执行远程数据插入,数据表出现数据的remotest表会删除刚插入的数据

本地数据库主键冲突报错,会执行全局事务的回滚,发现远程数据库

2.配合feign
开启2个服务注册到nacos上

调用方法,TM申请到了XID

远程服务获取到了相同的xid

执行完数据操作后,该服务RM会告诉TC执行完成

本地方法报错RM会告诉TC执行回滚,远程数据的RM也会被告知进行回滚

feign把xid添加到head中
String xid = RootContext.getXID();requestTemplate.header(RootContext.KEY_XID, xid);
public class FeignInterceptorConfig implements RequestInterceptor {Logger log = LoggerFactory.getLogger(FeignInterceptorConfig.class);public void apply(RequestTemplate requestTemplate) {RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();if (ObjectUtils.isEmpty(requestAttributes)){return ;}ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;HttpServletRequest request = attributes.getRequest();Enumeration<String> headerNames = request.getHeaderNames();//可以在这里将自定义请求头传递进去, key 请求, value 值//处理上游请求头信息,传递时继续携带if (headerNames != null) {while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();String values = request.getHeader(name);// 跳过 content-lengthif ("content-length".equals(name)) {continue;}requestTemplate.header(name, values);}//传递 seata 的 xidString xid = RootContext.getXID();requestTemplate.header(RootContext.KEY_XID, xid);}else {log.info("feign interceptor error header:{}", requestTemplate);}}
}
如果开启了hystrix会导致添加的head失效,因为获取的ServletRequestAttributes是null,要修改hystrix的策略。
参考下文
hystrix开启导致feign添加head失效
feign:hystrix:enabled: true
hystrix:command:default:execution:timeout:#如果enabled设置为false,则请求超时交给ribbon控制enabled: trueisolation:# 隔离策略strategy: SEMAPHORE thread:timeoutInMilliseconds: 100000
seata优缺点
优点:
1.业务侵入性低
2.TC(事务协调者)服务端能单独部署,利用nacos等注册中心能起多个

(图片截取于网络)
缺点:

(图片截取于网络)
相关文章:
SpringBoot+Seata在多数据源和feign中的简单使用
SpringBootSeata简单使用 目录seata执行过程安装seata下载seata使用自定义配置文件,NACOS为注册中心结合springboot实现AT模式1.多数据源引入依赖bootstrap.yml配置在使用的方法上用GlobalTransactional注解调用接口正常时调用接口报错时回滚2.配合feignseata优缺点seata执行过…...
计算机网络中的原码、反码、补码
写在前面 原码、反码、补码是计算机组成原理中的概念,是计算机网络的基础知识之一。这些概念是为了处理二进制数的符号位而引入的,常用于计算机中的整数运算,也常用于数据存储和传输等领域。因此,了解和掌握这些概念对于理解计算机…...
七、Bean的实例化方式
Spring为Bean提供了多种实例化方式,通常包括4种方式。(也就是说在Spring中为Bean对象的创建准备了多种方案,目的是:更加灵活) 第一种:通过构造方法实例化第二种:通过简单工厂模式实例化第三种&…...
Windows程序员学习Linux环境下VI(VIM)编辑器的使用方法
我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Windows程序员如何学习Linux环境知识。由于很多程序在Windows环境下开发好后,还要部署到Linux服务器上去,所以作为Windows程序员有必要学习Linux环境的知识。VI…...
react入门篇
react入门篇前言一、目标二、项目环境三、实现过程(干货满满💥💥💥)1.创建react项目2.arco design UI库3.路由模块化4. 状态管理zustand5. axios6. 路由守卫前言 提示:这里可以添加本文要记录的大概内容&a…...
阿赵的MaxScript学习笔记分享九《可编辑多面体的操作》
大家好,我是阿赵。这是MaxScript学习笔记分享的第九篇,可编辑多面体的操作。不知不觉写了这么多篇了,应该还有几篇就写完了。自己给自己加一下油。 在3DsMax里面如果需要建模,一般使用到的塌陷方式有3种,可编辑的网格、…...
【Redis场景5】集群秒杀优化-分布式锁
集群环境下的秒杀问题 前序 【Redis场景1】用户登录注册 【Redis场景2】缓存更新策略(双写一致) 【Redis场景3】缓存穿透、击穿问题 【Redis场景拓展】秒杀问题-全局唯一ID生成策略 【Redis场景4】单机环境下秒杀问题 在单机环境下的并发问题,我们可以使用相关…...
transformer目标检测开山之作detr
1. 将一个batch的图片输入backone获得feature。 (2,c,w,h)先输入resnet50中,得到(2,2048,w,h)。虽然这里channel不是256,但是在输入e…...
双指针法|位运算|离散化|区间合并
目录 双指针算法 位运算 离散化 序列合并 双指针算法 题目描述:1.输入n个单词,每个单词在输入的时候按空格隔开,之后打印出每个单词且换行 #include<iostream> #include <string>using namespace std; int main() {strin…...
Rockchip Android13 GKI开发指南
Rockchip Android13 GKI开发指南 文章目录Rockchip Android13 GKI开发指南GKI介绍Google upstream kernel下载及编译Rockchip SDK中GKI相关目录介绍Rockchip GKI编译代码修改编译固件烧写KO编译及修改添加新的模块驱动的方法调试ko方法开机log确认uboot阶段Android阶段KO加载KO…...
手把手教你原生JavaScript打造丝滑流畅的轮播图,让你的网站瞬间提升用户体验!
简介 轮播图是网页设计中常见的交互组件之一,用于展示多张图片或内容,让用户能够方便地浏览、切换和选择。本文将介绍如何使用原生 JavaScript 手写一个简单的轮播图,并且通过代码解释实现细节。 目录 简介 HTML 结构 CSS 样式 JavaScr…...
git常用基本操作
克隆远程代码更新本地代码 git clone <-b | -branch> [branch name] [repository URL] git pull #拉取远程仓库代码,更新本地仓库 git merge <branch-name> #合并目标分支 建立本地仓库分支 git branch #查看当…...
剑指 Offer —— 数组和字符串
文章目录剑指 Offer 04. 二维数组中的查找代码实现解题方案 思路算法步骤剑指 Offer 05. 替换空格题目描述代码实现解题方案 思路算法步骤剑指 Offer 11. 旋转数组的最小数字 - 解决方案题目描述剑指 Offer 04. 二维数组中的查找 在一个 n * m 的二维数组中: 每…...
Java 字符编码
编码:数据存储进计算机中需要转换为二进制存储,这个过程就是编码。 解码:计算机读取数据并展示在页面上,需要将二进制转换为人类语言的过程,叫做解码。 乱码:如果编码和解码时使用的码表不一样,…...
ubuntu-9-安装chrony时间同步
使用chrony搭建时间同步服务器 [Linux系列]Chrony时间同步服务器 配置chrony服务,实现服务器时间自动同步 linux上内网环境配置NTP时间同步详解 经验体会:解决Ubuntu 18.04Windows双系统时间不同步的问题 1 时间同步 我们知道一台电脑主机,…...
CMMI流程规范—服务与维护
服务与维护(Service and Maintenance, SM)是指产品销售之后的客户服务和产品维护。客户服务和产品维护的宗旨就是提高客户对产品以及对开发方的满意度。服务与维护过程域是SPP模型的重要组成部分。本规范阐述了服务与维护过程域的两个主要规程࿱…...
【蓝桥杯集训12】DFS(3 / 5)
目录 842. 排列数字 - DFS按位置枚举 843. n-皇后问题 - DFS按行枚举 165. 小猫爬山 - DFS枚举小猫 1209. 带分数 - DFS 3502. 不同路径数 - 842. 排列数字 - DFS按位置枚举 活动 - AcWing 题目: 给你一个整数n 要求将1~n的所有排列情况列出 比如:…...
Elasticsearch:构建自动补全功能 - Autocomplete
什么是自动补全(autocomplete)功能呢?我们举一个很常见的例子。 每当你去谷歌并开始打字时,就会出现一个下拉列表,其中列出了建议。 这些建议与查询相关并帮助用户完成查询。 Autocomplete 正如维基百科所说的…...
One UI 5.1 更新来了
之前一直在关注One UI 5.0里提到的视频通话背景功能模块,结果5.0版本推送的时候没有引入,有先行者计划博主说是5.1里肯定会有的;前一两天One UI 5.1更新来了,然而该功能还是没有引入,表示很遗憾;本次更新新…...
Python学习笔记11:文件
文件 打开文件 函数open的参数mode的最常见取值 值描述‘r’读取模式(默认值)‘w’写入模式‘x’独占写入模式‘a’附加模式‘b’二进制模式(与其他模式结合使用)‘t’文本模式(默认值,与其他模式结合使…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
前端工具库lodash与lodash-es区别详解
lodash 和 lodash-es 是同一工具库的两个不同版本,核心功能完全一致,主要区别在于模块化格式和优化方式,适合不同的开发环境。以下是详细对比: 1. 模块化格式 lodash 使用 CommonJS 模块格式(require/module.exports&a…...
李沐--动手学深度学习--GRU
1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...
