Table of contents
1. Modify the file.conf in the config directory
2. Modify registry.conf in the config directory
3. Mysql creates a new library and table
4. Initialize seata configuration
1. Modify the config.txt configuration
2. Add the configuration to nacos
2. Microservice integration seata
1. Create a new microservice and introduce related dependencies
3. Submodule yml configuration
1. Seata server construction
1. Download seata-server
Select the seata-server version of the microservice supporting version to download, and select the windows or linux version as needed.
Component version comparison table:
To build locally, I downloaded the Windows version 1.3.0
2. Start the seata server
The actual use needs to save some relevant information of the transaction to the database, and the relevant configuration needs to be modified before starting seata.
1. Modify the file.conf in the config directory
mode changed to db
The db module modifies the url, user, password of the database
## 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. Modify registry.conf in the config directory
This configuration is to register seata to the registration center, and the configuration of seata is persisted to the configuration center.
We use nacos as the registry and configuration center.
You need to change the type to nacos and modify the configuration under nacos respectively.
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 creates a new library and table
Download the source code of the corresponding version from the official website of seata.
After decompression, copy the entire script directory and put it in the folder after seata-server decompression.
Enter the script/server/db directory, and run the mysql.sql script in the mysql database (seata) configured in step 1 (mysql needs to create a new database named seata first)
4. Initialize seata configuration
Open the script/config-center directory under step 3,
1. Modify the config.txt configuration
Modify service.vgroupMapping.guangzhou=default, where the configuration at guangzhou must be consistent with the microservices of the project, which will be mentioned in the subsequent application.yml.
Modify store.mode=db
Modify some database-related configurations behind store.db.
2. Add the configuration to nacos
Make sure nacos is started.
Enter the script/config-center/nacos directory,
Open git here (the .sh file can be run with git under windows)
Run the command below (replace ip and port with actual ones)
sh nacos-config.sh -h ip -p port -g SEATA_GROUP -t seata-group
5. Start seata
Enter the seata/bin directory,
Double-click the seata-server.bat file, and the cmd window will display the startup status of the seata-server.
After the startup is successful, you can see that the seata-server service has been registered on the nacos client.
2. Microservice integration seata
1. Create a new microservice and introduce related dependencies
1. Microservice 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. Submodule pom.xml
Create new submodules alibaba-order-seata and alibaba-stock-seata
pom are
<?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. Submodule yml configuration
They are as follows, you can see that it echoes the guangzhou configuration above
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. Create a database
Create a database corresponding to the yml configuration,
Both databases execute the mysql.sql script in seata\script\client\at\db
5. Business module
1. Inventory service
Develop inventory-related interfaces
The core code is as follows
Respectively 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. Order module
There are global transaction annotations on the method of the implementation class, and the startup class configuration enables global transaction annotations
Order module calls inventory
main code
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. Test verification
At int a=1/0; break point.
When it is executed, the database will change the data, and the undo_log table will store the logs of the original data and the modified data.
Continue to execute the next line of code and report an error.
At this point, the transaction is rolled back, and the undo_log data is cleared after the rollback.
If int a=1/0; change to int a=1;
Then the code execution to this line is the same as before,
Proceed to the next line, as normal.
At this point, commit the transaction and clear the undo_log data.
So far, the distributed transaction environment has been built