概述

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。

更多的介绍可以参考官方文档:Seata快速入门
本篇主要是介绍Spring Cloud Alibaba + JPA 整合 Seata 的过程

安装Seata

  • 下载Seata,打开 https://github.com/seata/seata/releases,现在最新的是1.3.0,所以选择seata-server-1.3.0.tar.gz 进行下载,放到/opt
  • 解压Seata到/usr/local目录下
cd /opt
tar -zxvf seata-server-1.3.0.tar.gz -C /usr/local
cd /usr/local/seata/
  • 这边采用file单机模式(db模式相对麻烦一点,以后再另外介绍,从简单的先开始),直接运行命令启动即可
./bin/seata-server.sh

看到下面这个提示,说明启动成功,默认端口号8091


接下来介绍Spring Cloud Alibaba 接入Seata

业务场景

假设当前存在2个微服务:订单服务、支付服务。

  • 用户下单时,订单服务需要调用支付服务进行扣款
  • 当余额充足时下单成功,并全局提交事务
  • 当余额不足时下单失败,并全局回滚事务

版本说明

框架 版本号
Spring Boot 2.1.13.RELEASE
Spring Cloud Greenwich.SR6
Spring Cloud Alibaba 2.1.3.RELEASE
MySQL 8.0.11

创建父工程

创建父工程 hello-alibaba-seata,并引入依赖:

<dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud-version}</version><type>pom</type><scope>import</scope></dependency><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></dependencies>
</dependencyManagement><dependencies><!--Spring Boot--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!--Nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--Seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId></dependency><!--MySQL--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

创建公共服务 common-server

该工程主要封装公共的VO,由于测试场景比较简单,目前只有一个类

@Data
@Builder
public class ReduceAmountDto {private Long userId;private Integer amount;
}

创建支付服务 pay-order

在订单-支付的关系中,支付服务相当于provider,订单服务相当于consumer。因此,这边我们先创建支付服务。

  • 引入 common-server 依赖
    <dependencies><dependency><groupId>com.train</groupId><artifactId>common-server</artifactId><version>${project.parent.version}</version></dependency></dependencies>
  • 创建账户 Entity
@Data
@Entity
@Table(name = "t_account")
public class AccountInfo {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;/*** 用户id*/@Column(name = "user_id")private Long userId;/*** 余额*/@Column(name = "amount")private Integer amount;
}
  • 创建Dao
public interface AccountDao extends CrudRepository<AccountInfo, Long> {/***  根据userId获取账户信息*/@Query(value = "SELECT a FROM AccountInfo a where a.userId = :userId")AccountInfo getByUserId(@Param("userId") Long userId);/***  扣减账户余额*/@Modifying@Query("UPDATE AccountInfo SET amount = amount - :amount WHERE userId = :userId")Integer reduceAmount(@Param("userId") Long userId, @Param("amount") Integer amount);
}
  • 创建 Service
@Service
public class PayServiceImpl implements PayService {@Autowiredprivate AccountDao accountDao;@Override@Transactional(rollbackFor = Exception.class)public void reduceAmount(Long userId, Integer reduceAmount) throws Exception {checkAmount(userId, reduceAmount);accountDao.reduceAmount(userId, reduceAmount);}private void checkAmount(Long userId, Integer reduceAmount) throws Exception {AccountInfo accountInfo = accountDao.getByUserId(userId);if (accountInfo == null){throw new Exception("找不到账户信息");}if (accountInfo.getAmount() < reduceAmount){throw new Exception("余额不足");}}
}
  • 创建 controller
@RestController
@RequestMapping("/pay")
public class PayController {@Autowiredprivate PayService payService;@PostMapping("/reduceAmount")public String reduceAmount(@RequestBody ReduceAmountDto input) throws Exception {payService.reduceAmount(input.getUserId(), input.getAmount());return "扣款成功";}
}
  • application.yml
server:port: 8012spring:application:name: pay-serverjpa:database: mysqldatasource:url: jdbc:mysql://192.168.25.129:3306/pay_db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=falseusername: testpassword: 123456driver-class-name: com.mysql.cj.jdbc.Drivercloud:nacos:discovery:server-addr: 192.168.25.131:8848
management:endpoints:web:exposure:include: "*"seata:enabled: trueapplication-id: ${spring.application.name}tx-service-group: my_test_tx_groupservice:vgroup-mapping:my_test_tx_group: defaultgrouplist:default: 192.168.25.131:8091config:type: filefile:name: file.confregistry:type: filefile:name: file.confenable-auto-data-source-proxy: true

注意:如果用的不是MySQL8,就要改下 driver-class-name

创建订单服务 order-server

  • 引入 common-server 依赖
    <dependencies><dependency><groupId>com.train</groupId><artifactId>common-server</artifactId><version>${project.parent.version}</version></dependency></dependencies>
  • 创建订单 Entity
@Data
@Entity
@Table(name = "t_order")
public class Orders {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;/*** 用户id*/@Column(name = "user_id")private Long userId;/*** 金额*/@Column(name = "amount")private Integer amount;
}
  • 创建订单 Dao
public interface OrdersDao extends CrudRepository<Orders, Long> {}
  • 创建 Service
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrdersDao orderDao;@Autowiredprivate RestTemplate restTemplate;@Override@GlobalTransactionalpublic void save(Orders order) {orderDao.save(order);//扣款String reduceUrl = "http://pay-server/pay/reduceAmount";ReduceAmountDto input = ReduceAmountDto.builder().userId(order.getUserId()).amount(order.getAmount()).build();String result = restTemplate.postForObject(reduceUrl, input, String.class);log.info("调用pay-server结果:" + result);}
}

@GlobalTransactional 表示开启Seata全局事务

  • 创建 controller
@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/save")public String save(@RequestBody Orders order){orderService.save(order);return "操作结束";}
}

测试

  1. 启动Nacos
  2. 启动Seata
  3. 启动pay-server
  4. 启动order-server
  5. 调用创建订单接口 http://localhost:8011/order/save ,构造相应的测试数据进行测试就行

8.Spring Cloud Alibaba教程:整合Seata分布式事务相关推荐

  1. Spring cloud nacos注册中心 seata分布式事务

    准备环境的软件 seata 官网地址为 Seata 是什么 基本介绍 ,一下是一些大企业在使用 下载资源 GitHub - seata/seata: Seata is an easy-to-use, ...

  2. 7.Spring Cloud Alibaba教程:整合Dubbo实现RPC调用

    概述 Apache Dubbo 是一款高性能的.基于Java的开源RPC框架,它提供了以下特性: 基于接口的远程方法调用 智能负载均衡 服务自动注册和发现 高可扩展性 运行期流量调度 可视化的服务治理 ...

  3. 五Spring Cloud Alibaba基于Nacos构建分布式配置中心

      1.什么是Nacos 以下部分解释摘自于Nacos官方文档: Nacos 致力于帮助您发现.配置和管理微服务.Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据 ...

  4. Spring Cloud Alibaba教程:使用Nacos作为服务注册中心

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 什么是Nacos? Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易 ...

  5. 6.Spring Cloud Alibaba教程:Sentinel流量防卫兵的介绍与基本使用

    官网 https://sentinelguard.io/ 服务雪崩 微服务中各个服务之间通过http/rpc互相调用,假设其中1个服务因为网络或自身原因出现问题,调用这个服务就会出现线程堵塞,此时若有 ...

  6. 1.Spring Cloud Alibaba教程:简介

    概述 2018年10月31日,SpringCloudAlibaba 正式入驻 SpringCloud 官方孵化器,并在 Maven 中央库发布第一个版本. Spring Cloud for Aliba ...

  7. 3.Spring Cloud Alibaba教程:Nacos服务注册与发现

    概要 官网地址:Nacos官网和帮助文档 Nacos安装:Linux安装Nacos1.3.1(还没安装的先看这篇文章安装) Nacos主要作用:服务注册与发现.配置管理 本篇主要介绍的是服务注册与发现 ...

  8. springboot+dubbo+mybatisplus整合seata分布式事务

    介绍 默认采用AT模式的seata整合,项目已经传到码云,欢迎指点:https://gitee.com/itCjb/springboot-dubbo-mybatisplus-seata seata官网 ...

  9. 5.Spring Cloud Alibaba教程:Nacos整合Feign

    概述 Feign是一个声明式的http客户端.使用Feign只需要创建接口并加上对应的注解,就可以实现类似RestTemplate方式的调用,只是它将底层的http请求代码隐藏起来.另外,Feign默 ...

最新文章

  1. java简单springboot系统_Springboot系列 3 - 建立简单的用户登录系统
  2. 零基础自学python的app-编程零基础应当如何开始学习 Python?
  3. 用友ERP服务器的连接
  4. 美军开发远程人脸识别系统,实现1公里内目标识别
  5. 一本书看懂数字化转型|全新《2021年度案例观察》限时免费送
  6. eval() python_python基础-input函数和eval函数
  7. 【转载】正则表达式30分钟入门教程
  8. 【AtCoder】ARC083
  9. android listview局部刷新和模拟应用下载
  10. cydia多开微信_苹果ios怎么多开微信分身?
  11. 计算机基础和办公软件应用第23集,计算机基础及Office办公软件应用(Windows7+0ffice 2010版)...
  12. 李宏毅2020机器学习笔记1——CXK
  13. 2022年下半年网络工程师下午真题及答案解析
  14. WEB--3D立体魔方小游戏 (附源码)
  15. pmp-关键路径图和甘特图
  16. linux web 网站搭建
  17. C语言判断完全平方数(经典代码)
  18. 荣耀手表gspro是鸿蒙系统吗,荣耀手表gspro有哪些功能-功能说明
  19. 高薪程序员面试题精讲系列39之说说HashMap的特点及其底层数据结构
  20. 149php货币,149.99 USD to PHP

热门文章

  1. ABAP ALV检查单元格更新数据
  2. 大象公会:如何做万人传播的原创内容?
  3. SAP 销售与分销模块定价完全实施手册(SAP SD Pricing Handbook)
  4. ABAP 如何判断调用smartforms时是进行打印还是预览
  5. ABAP TC 响应双击事件
  6. Blanket PO(总括订单)
  7. co11n——生产订单确认的BAPI
  8. SAP读取财务报表版本的标准函数
  9. 类CL_ABAP_TYPEDESCR,动态取得运行时类型
  10. android 透明度变化,安卓获取屏幕的宽高并设置平移动画和透明度变化