seata实现分布式事务

简介: seata实现分布式事务

尽管世界和人生是坏透了,其中却有一件东西永远是好,那便是青春——显克维奇

首先是下载seata1.4.1

然后解压

先修改conf下的registry.conf

type改为nacos

进入bin

打开控制台运行seata-server.bat

然后在项目中引入依赖,记得需要分布式式事务的服务都要配置

1
2
3
4
5
<!--    seata 分布式事务    -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>

配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.ruben.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Optional;
/**
 * @ClassName: SeataConfig
 * @Description: 我还没有写描述
 * @Date: 2021/3/14 0014 16:53
 * *
 * @author: <achao1441470436@gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@Configuration
publicclassSeataConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
returnnewDruidDataSource();
    }
}

然后是项目中的配置文件

1
2
3
4
5
6
7
8
9
10
seata:
enabled:true
application-id:${spring.application.name}
tx-service-group:ruben
config:
type:file
file:
name:file.conf
service:
disable-global-transaction:false

如果之后启动一直报没配置disableGlobalTransaction

就需要新建一个file.confresources目录下

内容为

1
2
3
service{
    disableGlobalTransaction = false
}

接下来是编写两个接口

首先是调用方

controller

1
2
3
4
5
6
7
8
9
10
11
@RestController
@RequestMapping("user")
publicclassUserController {
@Resource
private UserService userService;
@GetMapping("order")
public AjaxJson order() {
return userService.order();
    }
}

service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Slf4j
@Service
publicclassUserServiceImplimplementsUserService {
@Resource
private MpOrderMapper mpOrderMapper;
@Resource
private ConsumerService consumerService;
@Override
@Transactional
@GlobalTransactional
public AjaxJson order() {
        consumerService.dropWare();
        mpOrderMapper.insert(OrderPO.builder().id(1L).build());
return AjaxJson.success();
    }
}

ConsumerService是使用feign远程调用另一个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ruben.feign;
import com.ruben.pojo.dto.PageDTO;
import com.ruben.utils.AjaxJson;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient("ruben-consumer")
publicinterfaceConsumerService {
@GetMapping("ware")
    AjaxJson dropWare();
}

MpOrderMappermybatis-plus调用数据库的方法

1
2
3
4
5
6
7
8
9
package com.ruben.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruben.pojo.po.OrderPO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
publicinterfaceMpOrderMapperextendsBaseMapper<OrderPO> {
}

然后是调用的ruben-consumer

首先也是引入依赖

其次是配置

1
2
3
4
5
6
7
8
9
10
seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: SEATA_GROUP
  config:
    type: file
    file:
      name: file.conf
  service:
    disable-global-transaction: false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.ruben.rubenproducerdemo.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Optional;
/**
 * @ClassName: SeataConfig
 * @Description: 我还没有写描述
 * @Date: 2021/3/14 0014 16:53
 * *
 * @author: <achao1441470436@gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@Configuration
publicclassSeataConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
returnnewDruidDataSource();
    }
}

然后是接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.ruben.rubenproducerdemo.controller;
import com.ruben.rubenproducerdemo.service.WareService;
import com.ruben.rubenproducerdemo.utils.AjaxJson;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * @ClassName: WareController
 * @Description: 我还没有写描述
 * @Date: 2021/3/13 0013 22:10
 * *
 * @author: <achao1441470436@gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@RestController
@RequestMapping("ware")
publicclassWareController {
@Resource
private WareService wareService;
@GetMapping
public AjaxJson dropWare() {
return wareService.dropWare();
    }
}

service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.ruben.rubenproducerdemo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruben.dao.WareMapper;
import com.ruben.rubenproducerdemo.pojo.po.WarePO;
import com.ruben.rubenproducerdemo.service.WareService;
import com.ruben.rubenproducerdemo.utils.AjaxJson;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
/**
 * @ClassName: WareServiceImpl
 * @Description: 我还没有写描述
 * @Date: 2021/3/13 0013 22:14
 * *
 * @author: <achao1441470436@gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@Service
publicclassWareServiceImplextendsServiceImpl<WareMapper, WarePO> implementsWareService {
@Override
@Transactional
public AjaxJson dropWare() {
WarePOware=this.getById("1");
        Optional.ofNullable(ware).map(WarePO::getWare).filter(w -> w <= 0).ifPresent(wi -> {
thrownewRuntimeException("卖光啦!");
        });
        Optional.ofNullable(ware).ifPresent(w -> this.updateById(WarePO.builder().id("1").ware(w.getWare() - 1).build()));
return AjaxJson.success("成功");
    }
}

我们开始测试

往数据库放条数据

首次调用接口时可以看到订单生成并且库存成功扣减

第二次调用发现抛出异常并成功回滚库存服务

至此,成功使用了seata实现了分布式事务

相关文章
|
2月前
|
SQL NoSQL 数据库
SpringCloud基础6——分布式事务,Seata
分布式事务、ACID原则、CAP定理、Seata、Seata的四种分布式方案:XA、AT、TCC、SAGA模式
SpringCloud基础6——分布式事务,Seata
|
6月前
|
存储 关系型数据库 MySQL
基于Seata实现分布式事务
通过以上步骤,你可以使用 Seata 实现分布式事务,确保在微服务架构中的事务一致性。Seata 支持多种语言和框架,能够满足不同业务场景的需求。欢迎关注威哥爱编程,一起学习成长。
160 1
|
3月前
|
关系型数据库 MySQL 数据库
SpringCloud2023中使用Seata解决分布式事务
对于分布式系统而言,需要保证分布式系统中的数据一致性,保证数据在子系统中始终保持一致,避免业务出现问题。分布式系统中对数据的操作要么一起成功,要么一起失败,必须是一个整体性的事务。Seata简化了这个使用过程。
85 2
|
3月前
|
Java 关系型数据库 MySQL
(二十七)舞动手指速写一个Seata-XA框架解决棘手的分布式事务问题
相信大家对于事务问题都不陌生,在之前《MySQL事务篇》中曾详解过MySQL的事务机制,在传统的单库环境下开发,咱们可依赖于MySQL所提供的事务机制,来确保单个事务内的一组操作,要么全部执行成功,要么全部执行失败。
|
3月前
|
Java Nacos Docker
"揭秘!Docker部署Seata遇上Nacos,注册成功却报错?这些坑你不得不防!一网打尽解决秘籍,让你的分布式事务稳如老狗!"
【8月更文挑战第15天】在微服务架构中,Nacos搭配Seata确保数据一致性时,Docker部署Seata后可能出现客户端连接错误,如“can not connect to services-server”。此问题多由网络配置不当、配置文件错误或版本不兼容引起。解决策略包括:调整Docker网络设置确保可达性;检查并修正`file.conf`和`registry.conf`中的Nacos地址和端口;验证Seata与Nacos版本兼容性;修改配置后重启服务;参考官方文档和最佳实践进行配置。通过这些步骤,能有效排除故障,保障服务稳定运行。
264 0
|
5月前
|
Java 数据库 开发者
深入解析 Spring Cloud Seata:分布式事务的全面指南
深入解析 Spring Cloud Seata:分布式事务的全面指南
314 1
|
5月前
|
存储 关系型数据库 Java
技术经验解读:三种分布式事务LCN、Seata、MQ
技术经验解读:三种分布式事务LCN、Seata、MQ
177 0
|
5月前
|
消息中间件 SQL 关系型数据库
分布式事务-seata
分布式事务-seata
147 0
|
5月前
|
SQL 数据库
Seata:分布式事务
Seata:分布式事务
171 0
|
6月前
|
关系型数据库 MySQL 数据库
分布式事务Seata
分布式事务Seata
62 1
分布式事务Seata

热门文章

最新文章