seata下载部署
官方下载地址:https://seata.apache.org/
也可以到阿里云盘中下载


修改配置

这里以nacos集群版本举例子,也可以部署本地file的单机版本
server:
port: 7091
spring:
application:
name: seata-server
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 192.168.1.111:8848
namespace: jm-dev
group: DEFAULT_GROUP
username: jm-server
password: jm-inner-0311.
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
data-id: jmSeataServer.yml
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 192.168.1.111:8848
group: DEFAULT_GROUP
namespace: jm-dev
cluster: default
username: jm-server
password: jm-inner-0311.
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3wyyztwj
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
Copy to clipboardErrorCopied在nacos中创建公用配置文件jmSeataServer.yml
内容:
# jm-seata
seata:
store:
# support: file 、 db 、 redis
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.1.40:3306/pig_seata?rewriteBatchedStatements=true
user: root
password: 123456
min-conn: 10
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 1000
max-wait: 5000
logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstashCopy to clipboardErrorCopied注意,如果是连接的数据库,那么需要提前创建好数据库和对应表
表sql在源码中有,如


启动


访问后台

服务集成seata
这里创建公共包

添加依赖
<!-- seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!-- seata kryo 序列化-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-serializer-kryo</artifactId>
</dependency>Copy to clipboardErrorCopied增加配置类,指定seata的配置文件yml
package com.xxx.common.seata.config;
import com.xxx.common.core.factory.YamlPropertySourceFactory;
import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* Seata 配置类
*
* @author jm-wss
* @date 2022/3/29
*/
@PropertySource(value = "classpath:seata-config.yml", factory = YamlPropertySourceFactory.class)
@EnableAutoDataSourceProxy(useJdkProxy = true)
@Configuration(proxyBeanMethods = false)
public class SeataAutoConfiguration {
}
Copy to clipboardErrorCopied在resource中创建seata-config.yml
seata:
enabled: true
tx-service-group: jm_tx_group # 事务群组(可以每个应用独立取名,也可以使用相同的名字)
client:
rm-report-success-enable: true
rm-table-meta-check-enable: false # 自动刷新缓存中的表结构(默认false)
rm-report-retry-count: 5 # 一阶段结果上报TC重试次数(默认5)
rm-async-commit-buffer-limit: 10000 # 异步提交缓存队列长度(默认10000)
rm:
lock:
lock-retry-internal: 10 # 校验或占用全局锁重试间隔(默认10ms)
lock-retry-times: 30 # 校验或占用全局锁重试次数(默认30)
lock-retry-policy-branch-rollback-on-conflict: true # 分支事务与其它全局回滚事务冲突时锁策略(优先释放本地锁让回滚成功)
tm-commit-retry-count: 3 # 一阶段全局提交结果上报TC重试次数(默认1次,建议大于1)
tm-rollback-retry-count: 3 # 一阶段全局回滚结果上报TC重试次数(默认1次,建议大于1)
undo:
data-validation: true # 二阶段回滚镜像校验(默认true开启)
log-serialization: kryo # undo序列化方式(默认jackson 不支持 LocalDateTime)
log-table: undo_log # 自定义undo表名(默认undo_log)
log:
exceptionRate: 100 # 日志异常输出概率(默认100)
support:
spring:
datasource-autoproxy: true
service:
vgroup-mapping:
jm_tx_group: default # TC 集群(必须与seata-server保持一致)
enable-degrade: false # 降级开关
disable-global-transaction: false # 禁用全局事务(默认false)
grouplist:
default: 192.168.1.239:8091
transport:
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
server-executor-thread-prefix: NettyServerBizHandler
share-boss-worker: false
client-selector-thread-prefix: NettyClientSelector
client-selector-thread-size: 1
client-worker-thread-prefix: NettyClientWorkerThread
type: TCP
server: NIO
heartbeat: true
serialization: seata
compressor: none
enable-client-batch-send-request: true # 客户端事务消息请求是否批量合并发送(默认true)
registry:
file:
name: file.conf
type: file
config:
file:
name: file.conf
type: file
Copy to clipboardErrorCopiedresource中创建spring的自动配置文件
创建路径META-INF.spring 注意,这是两个目录,要一个个创建
创建文件 :org.springframework.boot.autoconfigure.AutoConfiguration.imports
内容:
com.xxxx.common.seata.config.SeataAutoConfiguration
Copy to clipboardErrorCopied业务服务引入这个公共模块即可
如:

注意,每个参与事务的数据库都需要创建seata的业务表
-- auto-generated definition
create table undo_log
(
id bigint auto_increment
primary key,
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,
ext varchar(100) null,
constraint ux_undo_log
unique (xid, branch_id)
)
charset = utf8
row_format = DYNAMIC;

测试
package com.xxxxx.iotd.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xxxxx.common.core.constant.SecurityConstants;
import com.xxxxx.common.core.exception.BusinessException;
import com.xxxxx.common.core.util.R;
import com.xxxxx.common.security.annotation.Inner;
import com.xxxxx.iotd.api.feign.RemoteIotdService;
import com.xxxxx.iotd.finance.entity.IotdOrderEntity;
import com.xxxxx.iotd.finance.mapper.IotdOrderMapper;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
@RequestMapping("/test")
@Tag(description = "test" , name = "test" )
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class TestController {
private final IotdOrderMapper iotdOrderMapper;
//Feign
private final RemoteIotdService remoteIotdService;
@Inner
@GetMapping(value = "/test1")
public R<String> test1(@RequestParam(value = "p1")String p1, @RequestParam(value = "p2")String p2){
iotdOrderMapper.update(new IotdOrderEntity(),new LambdaUpdateWrapper<IotdOrderEntity>()
.eq(IotdOrderEntity::getOrderCode,"D1914190876176928768R1")
.set(IotdOrderEntity::getOrderRemarks,p2)
);
return R.ok();
}
@GlobalTransactional
@Inner(value = false)
@GetMapping(value = "/test2")
public R<String> test2(@RequestParam(value = "p1")String p1, @RequestParam(value = "p2")String p2){
iotdOrderMapper.update(new IotdOrderEntity(),new LambdaUpdateWrapper<IotdOrderEntity>()
.eq(IotdOrderEntity::getOrderCode,p1)
.set(IotdOrderEntity::getOrderRemarks,p2)
);
R<String> stringR = remoteIotdService.test1(p1, p2 + "_test1"
, SecurityConstants.FROM_IN);
System.out.println(JSONObject.toJSONString(stringR));
if(!stringR.isSuccess()){
throw new BusinessException(stringR.getMsg());
}
//模拟异常
if("22222".equals(p2)){
throw new BusinessException("自定义异常");
}
return R.ok();
}
}
Copy to clipboardErrorCopied正常请求

数据正常修改

异常请求


数据没有变化,回退了

打断点,看下seata后台数据情况

