Seata服务搭建&配置&使用
是什么
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
Seata 组成
全局事务ID XID
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
工作流程
简单的说就是:
a.申请全局事务ID
b.进行本地事务操作
c.提交或回滚后释放全局事务
Seata服务部署(MySql+Nacos)
下载
23/03/06最新稳定版1.6.1
Releases · seata/seata (github.com)
创建Seata数据库
进入下载后解压目录,有sql
seata\script\server\db
修改配置
找到解压后目录seata\conf,修改application.yml
分别修改seata:config、registry、store
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
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:
# 配置可从nacos读取,nacos使用见 https://www.cnblogs.com/rb2010/p/17145183.html
# config下配置内容见 解压目录seata\conf\application.example.yml
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 10.20.30.227:9999 #nacos地址
namespace:
group: SEATA_GROUP
username:
password:
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
data-id: seataServer.properties #nacos配置的data-id
# 将seata注册进nacos
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 10.20.30.227:9999
group: SEATA_GROUP
namespace:
cluster: default
username:
password:
context-path:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key:
#secret-key:
#修改事务信息存储到MySql
store:
# support: file 、 db 、 redis
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://10.20.30.13:3306/seata?rewriteBatchedStatements=true
user: root
password: root
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
# 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
启动&验证
注: 堆内存建议分配2G,堆外内存1G
执行seata\bin下seata-server.bat或seata-server.sh
访问http://10.20.30.94:7091/
SeataDocker\K8S\高可用部署
项目搭建
本次测试准备使用三个项目,订单、库存、积分,流程为下单后减库存加积分
数据库
a.积分库
CREATE DATABASE /*!32312 IF NOT EXISTS*/`integral` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `integral`;
/*Table structure for table `integral` */
DROP TABLE IF EXISTS `integral`;
CREATE TABLE `integral` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`count` int(11) DEFAULT NULL COMMENT '积分',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
b.订单库
CREATE DATABASE /*!32312 IF NOT EXISTS*/`order` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `order`;
/*Table structure for table `order` */
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
c.库存库
CREATE DATABASE /*!32312 IF NOT EXISTS*/`stock` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `stock`;
/*Table structure for table `stock` */
DROP TABLE IF EXISTS `stock`;
CREATE TABLE `stock` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`stock` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
业务代码
订单服务
pom
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.seata/seata-spring-boot-starter -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2021.1</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.yml
todo default_tx_group
server:
port: 8081
spring:
application:
name: order-project
cloud:
nacos:
discovery:
server-addr: 10.20.30.227:9999
alibaba:
seata:
default_tx_group: my_tx #nacos配置,具体见下图
#shardingsphere相关配置
shardingsphere:
datasource:
names: masterdb,slavedb1 #库名,只是名字
masterdb: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/order?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/order?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
masterslave:
name: dbs
master-data-source-name: masterdb #主库
slave-data-source-names: slavedb1 #多个从库
load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机 ROUND_ROBIN 轮训
props:
sql:
show: true #输出日志
启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class);
}
}
service
IntegralService.java
@Service
@FeignClient(value = "integral-project") //后面积分服务的服务名称
public interface IntegralService {
@GetMapping(value = "/saveIntegral") //后面积分服务的接口地址
void saveIntegral(@RequestParam("integralId") Integer integralId );
}
StockService.java
@Service
@FeignClient(value = "stock-project") //后面库存服务的服务名称
public interface StockService {
@GetMapping("/stock") //后面库存服务的接口地址
void stock(@RequestParam(value = "stockId") Integer stockId);
}
controller
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@Autowired
private IntegralService integralService;
@Autowired
private StockService stockService;
@GetMapping("saveOrder")
@GlobalTransactional //开启分布式事务
public void saveOrder(){
Order order=new Order();
order.setOrderNo(LocalDateTime.now().toString());
orderService.save(order);
stockService.stock(1);
integralService.saveIntegral(1);
}
}
库存服务
pom
同订单服务
yml
server:
port: 8082
spring:
application:
name: stock-project
cloud:
alibaba:
seata:
default_tx_group: my_tx #nacos配置
nacos:
discovery:
server-addr: 10.20.30.227:9999
#shardingsphere相关配置
shardingsphere:
datasource:
names: masterdb,slavedb1 #库名,只是名字
masterdb: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/stock?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/stock?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
masterslave:
name: dbs
master-data-source-name: masterdb #主库
slave-data-source-names: slavedb1 #多个从库
load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机 ROUND_ROBIN 轮训
props:
sql:
show: true #输出日志
controller
@RestController
public class StockController {
@Autowired
private StockService stockService;
@GetMapping("stock")
public void stock(Integer stockId){
Stock stock = stockService.getById(stockId);
stock.setStock(stock.getStock()-1);
stockService.updateById(stock);
}
}
启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class StockApplication {
public static void main(String[] args) {
SpringApplication.run(StockApplication.class,args);
}
}
积分服务
pom
同订单服务
yml
server:
port: 8083
spring:
application:
name: integral-project
cloud:
alibaba:
seata:
default_tx_group: my_tx #nacos配置
nacos:
discovery:
server-addr: 10.20.30.227:9999
#shardingsphere相关配置
shardingsphere:
datasource:
names: masterdb,slavedb1 #库名,只是名字
masterdb: #主库
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/integral?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
slavedb1: #从库1
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/integral?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT
username: root
password: 123
masterslave:
name: dbs
master-data-source-name: masterdb #主库
slave-data-source-names: slavedb1 #多个从库
load-balance-algorithm-type: ROUND_ROBIN #RANDOM随机 ROUND_ROBIN 轮训
props:
sql:
show: true #输出日志
controller
@RestController
public class IntegralController {
@Autowired
private IntegralService integralService;
@GetMapping("saveIntegral")
public void saveIntegral(Integer integralId){
Integral integral = integralService.getById(integralId);
integral.setCount(integral.getCount()+1);
integralService.updateById(integral);
}
}
启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class IntegralApplication {
public static void main(String[] args) {
SpringApplication.run(IntegralApplication.class,args);
}
}
nacos配置
测试
当调用订单服务order/saveOrder时,如果库存服务或者积分服务出异常了,那么三个库都会回滚