目录
一、seata服务端搭建
1、下载seata-server
选择微服务配套版本的seata-server下载,根据需要选择windows或者linux版本的。
Releases · seata/seata · GitHub
组件版本对照表:

本地搭建我下载的是1.3.0的windows版本
2、seata服务端启动
实际使用需要将事务的一些相关信息存到数据库,启动seata前需要修改相关配置。
1、修改config目录下的file.conf
mode改为db
db模块修改数据库的url,user,password
## transaction log store, only used in seata-server
store {
## store mode: file、db、redis
mode = "db"## file store property
file {
## store location dir
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
maxBranchSessionSize = 16384
# globe session size , if exceeded throws exceptions
maxGlobalSessionSize = 512
# file buffer size , if exceeded allocate new buffer
fileWriteBufferCacheSize = 16384
# when recover batch read size
sessionReloadReadSize = 100
# async, sync
flushDiskMode = async
}## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://101.37.23.0:3306/seata"
user = "root"
password = "nymi@2023"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}## redis store property
redis {
host = "127.0.0.1"
port = "6379"
password = ""
database = "0"
minConn = 1
maxConn = 10
queryLimit = 100
}}
2.修改config目录下registry.conf
此配置是将seata注册到注册中心,seata的配置持久化到配置中心。
我们使用nacos作为注册中心和配置中心。
需要分别将type改为nacos并修改nacos下的配置。
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"nacos {
application = "seata-server"
serverAddr = "101.37.23.0:80"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
eureka {
serviceUrl = "http://localhost:8761/eureka"
application = "default"
weight = "1"
}
redis {
serverAddr = "localhost:6379"
db = 0
password = ""
cluster = "default"
timeout = 0
}
zk {
cluster = "default"
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
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、etcd3
type = "nacos"nacos {
serverAddr = "101.37.23.0:80"
namespace = ""
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
consul {
serverAddr = "127.0.0.1:8500"
}
apollo {
appId = "seata-server"
apolloMeta = "http://192.168.1.204:8801"
namespace = "application"
}
zk {
serverAddr = "127.0.0.1:2181"
sessionTimeout = 6000
connectTimeout = 2000
username = ""
password = ""
}
etcd3 {
serverAddr = "http://localhost:2379"
}
file {
name = "file.conf"
}
}
3、mysql新建库和表
下载seata官网的对应版本的源码。
解压过后复制整个script目录放到seata-server解压后的文件夹下。
进入script/server/db目录,造第1步配置的mysql数据库(seata)中运行mysql.sql脚本(mysql需要先新建名为seata的数据库)
4、初始化seata配置
打开第3步下的 script/config-center目录,
1、修改config.txt配置
修改service.vgroupMapping.guangzhou=default,其中guangzhou处的配置要和项目的微服务一致,后续application.yml里会讲到。
修改store.mode=db
修改store.db.后面的一些数据库相关的配置
2、配置添加到nacos
确保nacos已经启动。
进入script/config-center/nacos目录,
在此处打开git(.sh文件windows下借助git可以运行)
运行下面的命令(ip和port替换为实际的)
sh nacos-config.sh -h ip -p port -g SEATA_GROUP -t seata-group
5、启动seata
进入seata/bin目录,
双击seata-server.bat文件,cmd窗口会显示seata-server的启动情况。
启动成功后,可以在nacos客户端看到seata-server服务已经注册进来了。

二、微服务整合seata
1、新建微服务,引入相关依赖
1、微服务pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>seata</module>
</modules>
<groupId>com.wind.springcloud</groupId>
<artifactId>alibaba</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>alibaba</name>
<description>springcloudalibaba</description>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<spring.cloud.alibaba.version>2.2.5.RELEASE</spring.cloud.alibaba.version>
<spring.boot.version>2.3.11.RELEASE</spring.boot.version>
<spring.cloud.version> Hoxton.SR8</spring.cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- alibaba版本管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springboot版本管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springcloud版本管理-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、seata模块pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>alibaba</artifactId>
<groupId>com.wind.springcloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.wind.springcloud</groupId>
<artifactId>seata</artifactId>
<version>0.0.1-SNAPSHOT</version>
<modules>
<module>order-seata</module>
<module>stock-seata</module>
<module>alibaba-order-seata</module>
<module>alibaba-stock-seata</module>
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
<!-- nacos服务注册发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 添加openfeign的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
</dependencies>
</project>
2、子模块pom.xml
新建子模块alibaba-order-seata和alibaba-stock-seata
pom分别是
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata</artifactId>
<groupId>com.wind.springcloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>alibaba-order-seata</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>seata</artifactId>
<groupId>com.wind.springcloud</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>alibaba-stock-seata</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
3、子模块yml配置
分别如下,可以看到呼应上面的guangzhou配置
server:
port: 8200
spring:
application:
name: order
cloud:
nacos:
server-addr: 101.37.23.0:80
discovery:
username: nacos
password: nacos
alibaba:
seata:
tx-service-group: guangzhou
datasource:
username: root
password: nymi@2023
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://101.37.23.0:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
mybatis:
mapper-locations: classpath:/mappers/**/*Mapper.xml
seata:
registry:
type: nacos
nacos:
server-addr: 101.37.23.0:80
application: seata-server
username: nacos
password: nacos
group: SEATA_GROUP
config:
type: nacos
nacos:
server-addr: 101.37.23.0:80
username: nacos
password: nacos
group: SEATA_GROUP
server:
port: 8201
spring:
application:
name: stock
cloud:
nacos:
server-addr: 101.37.23.0:80
discovery:
username: nacos
password: nacos
alibaba:
seata:
tx-service-group: guangzhou
datasource:
username: root
password: nymi@2023
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://101.37.23.0:3306/seata_stock?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
mybatis:
mapper-locations: classpath:/mappers/**/*Mapper.xml
seata:
registry:
type: nacos
nacos:
server-addr: 101.37.23.0:80
application: seata-server
username: nacos
password: nacos
group: SEATA_GROUP
config:
type: nacos
nacos:
server-addr: 101.37.23.0:80
username: nacos
password: nacos
group: SEATA_GROUP
4、建立数据库
分别建立对应yml配置的数据库,
两个数据库均执行 seata\script\client\at\db中的mysql.sql的脚本
5、业务模块
1、库存服务
开发库存相关的接口
核心代码如下
分别是Stock.class
package com.wind.model;
import lombok.Data;
/**
* @author dongguanghui
* @date 2023/6/29 14:20
*/
@Data
public class Stock {
private Integer id;
private Integer productId;
private Integer count;
}
StockServiceImpl.class
package com.wind.service.impl;
import com.wind.mapper.StockMapper;
import com.wind.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author dongguanghui
* @date 2023/6/29 14:19
*/
@Service
public class StockServiceImpl implements StockService {
@Autowired
StockMapper stockMapper;
public void reduct(Integer productId) {
stockMapper.reduct(productId);
System.out.println("更新商品:"+productId);
}
}
stockMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wind.mapper.StockMapper">
<update id="reduct">
update stock set `count` = `count` -1
where product_id = #{productId}
</update>
</mapper>
2、订单模块
实现类的方法上有全局事务的注解,启动类配置开启全局事务注解
订单模块调用库存
主要代码
OrderSeataApplication.class
package com.wind;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.RestTemplate;
/**
* @author dongguanghui
* @date 2023/6/29 14:17
*/
@SpringBootApplication
@EnableFeignClients
@EnableTransactionManagement
public class OrderSeataApplication {
public static void main(String[] args) {
SpringApplication.run(OrderSeataApplication.class,args);
}
}
OrderController.class
package com.wind.controller;
import com.wind.model.Order;
import com.wind.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author dongguanghui
* @date 2023/6/29 11:53
*/
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
OrderService orderService;
@RequestMapping("/add")
public String add() {
Order order = new Order();
order.setProductId(9);
order.setStatus(0);
order.setTotalAmount(100);
orderService.create(order);
return "下单成功";
}
}
OrderServiceImpl.class
package com.wind.service.impl;
import com.wind.api.StockService;
import com.wind.mapper.OrderMapper;
import com.wind.model.Order;
import com.wind.service.OrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
/**
* @author dongguanghui
* @date 2023/6/29 14:19
*/
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
OrderMapper orderMapper;
@Autowired
StockService stockService;
@GlobalTransactional
public Order create(Order order) {
// 插入订单
orderMapper.insert(order);
// 扣减库存
stockService.reduct(order.getProductId());
int a=1/0;
return order;
}
}
Order.class
package com.wind.model;
import lombok.Data;
/**
* @author dongguanghui
* @date 2023/6/29 14:20
*/
@Data
public class Order {
private Integer id;
private Integer productId;
private Integer status;
private Integer totalAmount;
}
StockService.class
package com.wind.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author dongguanghui
* @date 2023/6/29 17:26
*/
@FeignClient(value = "stock",path = "/stock")
public interface StockService {
@RequestMapping("/reduct")
public String reduct(@RequestParam("productId") Integer productId);
}
OrderMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wind.mapper.OrderMapper">
<insert id="insert" parameterType="com.wind.model.Order">
insert into `order` (product_id,`status`,total_amount)
values
(#{productId},#{status},#{totalAmount})
</insert>
</mapper>
6、测试验证
在int a=1/0;打断点。
当执行到时,数据库将会改变数据,undo_log表会存原始数据和修改后数据的日志。
继续执行代码下一行,报错。
此时,事务回滚,回滚后undo_log数据清空。
如果int a=1/0; 改为int a=1;
则代码执行到这一行与前面一致,
继续执行下一行,正常。
此时,提交事务,undo_log数据清空。
至此,分布式事务环境搭建完毕
该文详细介绍了如何搭建Seata服务端,包括下载seata-server,配置file.conf和registry.conf,创建MySQL数据库和表,以及启动seata。接着,文章展示了微服务整合Seata的过程,包括引入相关依赖,配置YML文件,并提供了库存和订单服务的示例代码。整个过程涉及Nacos作为注册中心和配置中心。
2317

被折叠的 条评论
为什么被折叠?



