官方文档
https://seata.io/zh-cn/docs/overview/what-is-seata.html
下载 seata-server
https://github.com/seata/seata/releases/download/v1.5.2/seata-server-1.5.2.zip
安装 seata-server
下载后解压即可
创建seata-server专属数据库
创建数据库 ‘seata’(名字随意),并通过以下脚本创建该库的表:
mysql:https://github.com/seata/seata/tree/v1.5.2/script/server/db/mysql.sql
oracle:https://github.com/seata/seata/tree/v1.5.2/script/server/db/oracle.sql
postgresql:https://github.com/seata/seata/tree/v1.5.2/script/server/db/postgresql.sql
配置seata-server
打开seata/conf/application.yml配置文件如下
(使用其他注册方式请参考seata/conf/application.example.yml )
server:
port: 7091
spring:
application:
name: seata-server
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_logstash
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: file
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: file
store:
# support: file 、 db 、 redis
mode: file
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
参考下面代码修改seata节点下的registry、store节点
seata:
registry:
type: eureka
eureka:
service-url: http://admin:admin@127.0.0.1:8088/eureka
application: seata-server
weight: 1
store:
# support: file 、 db 、 redis
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://your_db_server_ip:3306/seata?rewriteBatchedStatements=true
user: admin
password: admin
min-conn: 5
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 100
max-wait: 5000
启动seata-server
先启动Eureka注册中心
eureka配置如下
eureka:
server:
response-cache-update-interval-ms: 2000
eviction-interval-timer-in-ms: 2000
client:
fetch-registry: false
register-with-eureka: false
service-url:
defaultZone: http://admin:admin@localhost:8088/eureka/
再启动Seata服务
执行 seata\bin 目录下的 seata-server.bat (windows)/ seata-server.sh (linux或mac)启动seata服务
子服务的数据库添加seata客户端专属表
sql脚本:https://github.com/seata/seata/tree/v1.5.2/script/client/at/db
用到seata的数据库都需要添加该表
子服务添加seata依赖
<!-- seata -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
添加feign依赖 (版本跟随springcloud,无需添加version节点)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
子服务添加seata客户端配置
seata:
application-id: seata-client0 #seata客户端id
tx-service-group: default_tx_group #照搬即可
service:
vgroup-mapping:
default_tx_group: seata-server #照搬即可
registry:
type: eureka
eureka:
service-url: http://admin:admin@localhost:8088/eureka
weight: 1
seata事务管理测试(举例)
假设有两个子服务用到seata,分别是service-edu、service-school(简称edu、school),edu、school 服务的数据库是分开的,但属于通一个微服务。
edu下包含服务
/**添加新生 */
void addNewStudent()
school下包含服务
/**获取新生列表 */
List<Stu> getStudent();
/**修改新生状态位在校生 */
boolean updtStudent2Old(Stu stu);
需求:把school的新生数据写入到edu后修改新生状态.(由edu调用school的服务)
在edu项目下添加schoolFeignClient
package com.example.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import x.Stu;
//import com.example.config.FeignClientConfig;
@FeignClient(name = "service-school")
public interface SchoolFeignClient {
//映射服务
@RequestMapping(value = "/getStudent", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
List<Stu> getStudent();
@RequestMapping(value = "/updtStudent2Old", method = RequestMethod.POST)
boolean updtStudent2Old(Stu stu);
}
使用seata事务注解
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import io.seata.spring.annotation.GlobalTransactional;
import x.Stu;
public interface EduService {
@Autowired
private EduStudentSerevice eduStudentService;
@Autowired
private SchoolFeignClient schoolFeignClient;
@GlobalTransactional //seata事务管理注解
private void String addNewStudentFromScholl() {
List<Stu> stus = schoolFeignClient.getStudent();
for(Stu stu: stus) {
eduStudentService.addNewStudent(stu);
boolean updtRes = schoolFeignClient.updtStudent2Old(stu);
if(!updtRes) {
throw new RuntimeException("更新新生状态失败,执行回滚");
}
}
}
}