8.Spring Cloud Alibaba教程:整合Seata分布式事务
概述
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 "操作结束";}
}
测试
- 启动Nacos
- 启动Seata
- 启动pay-server
- 启动order-server
- 调用创建订单接口 http://localhost:8011/order/save ,构造相应的测试数据进行测试就行
8.Spring Cloud Alibaba教程:整合Seata分布式事务相关推荐
- Spring cloud nacos注册中心 seata分布式事务
准备环境的软件 seata 官网地址为 Seata 是什么 基本介绍 ,一下是一些大企业在使用 下载资源 GitHub - seata/seata: Seata is an easy-to-use, ...
- 7.Spring Cloud Alibaba教程:整合Dubbo实现RPC调用
概述 Apache Dubbo 是一款高性能的.基于Java的开源RPC框架,它提供了以下特性: 基于接口的远程方法调用 智能负载均衡 服务自动注册和发现 高可扩展性 运行期流量调度 可视化的服务治理 ...
- 五Spring Cloud Alibaba基于Nacos构建分布式配置中心
1.什么是Nacos 以下部分解释摘自于Nacos官方文档: Nacos 致力于帮助您发现.配置和管理微服务.Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据 ...
- Spring Cloud Alibaba教程:使用Nacos作为服务注册中心
点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! 什么是Nacos? Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易 ...
- 6.Spring Cloud Alibaba教程:Sentinel流量防卫兵的介绍与基本使用
官网 https://sentinelguard.io/ 服务雪崩 微服务中各个服务之间通过http/rpc互相调用,假设其中1个服务因为网络或自身原因出现问题,调用这个服务就会出现线程堵塞,此时若有 ...
- 1.Spring Cloud Alibaba教程:简介
概述 2018年10月31日,SpringCloudAlibaba 正式入驻 SpringCloud 官方孵化器,并在 Maven 中央库发布第一个版本. Spring Cloud for Aliba ...
- 3.Spring Cloud Alibaba教程:Nacos服务注册与发现
概要 官网地址:Nacos官网和帮助文档 Nacos安装:Linux安装Nacos1.3.1(还没安装的先看这篇文章安装) Nacos主要作用:服务注册与发现.配置管理 本篇主要介绍的是服务注册与发现 ...
- springboot+dubbo+mybatisplus整合seata分布式事务
介绍 默认采用AT模式的seata整合,项目已经传到码云,欢迎指点:https://gitee.com/itCjb/springboot-dubbo-mybatisplus-seata seata官网 ...
- 5.Spring Cloud Alibaba教程:Nacos整合Feign
概述 Feign是一个声明式的http客户端.使用Feign只需要创建接口并加上对应的注解,就可以实现类似RestTemplate方式的调用,只是它将底层的http请求代码隐藏起来.另外,Feign默 ...
最新文章
- java简单springboot系统_Springboot系列 3 - 建立简单的用户登录系统
- 零基础自学python的app-编程零基础应当如何开始学习 Python?
- 用友ERP服务器的连接
- 美军开发远程人脸识别系统,实现1公里内目标识别
- 一本书看懂数字化转型|全新《2021年度案例观察》限时免费送
- eval() python_python基础-input函数和eval函数
- 【转载】正则表达式30分钟入门教程
- 【AtCoder】ARC083
- android listview局部刷新和模拟应用下载
- cydia多开微信_苹果ios怎么多开微信分身?
- 计算机基础和办公软件应用第23集,计算机基础及Office办公软件应用(Windows7+0ffice 2010版)...
- 李宏毅2020机器学习笔记1——CXK
- 2022年下半年网络工程师下午真题及答案解析
- WEB--3D立体魔方小游戏 (附源码)
- pmp-关键路径图和甘特图
- linux web 网站搭建
- C语言判断完全平方数(经典代码)
- 荣耀手表gspro是鸿蒙系统吗,荣耀手表gspro有哪些功能-功能说明
- 高薪程序员面试题精讲系列39之说说HashMap的特点及其底层数据结构
- 149php货币,149.99 USD to PHP