Springcloud结合mybatis-plus与nacos实现分布式事务seata

简介: Springcloud结合mybatis-plus与nacos实现分布式事务seata

文章目录

简介

项目示例

seata配置启动

账户模块

mapper

启动账户

库存模块

mapper

启动账户模块

订单模块

依赖

yml配置

controller类

服务类

测试库存模块

获取商品

扣减库存

测试账户模块

获取用户

扣减账户

测试订单

不加事务模拟下单

不加事务模拟异常

加事务模拟异常

简介

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

项目示例

用户购买商品的业务逻辑。整个业务逻辑由3个微服务提供支持:

库存服务:对给定的商品扣除仓储数量。

订单服务:根据采购需求创建订单。

帐户服务:从用户帐户中扣除余额。

8e0b64b55b8c4e32a10dd302b60c6ccb.png

seata配置启动

#初始化seata 的nacos配置

cd conf

sh nacos-config.sh 127.0.0.1

#启动seata-server

cd bin

seata-server.bat -p 8091 -h 127.0.0.1 -m db

61be66431fa74132a66b092770ea5906.png

配置可以参考官方的配置。

账户模块

mapper

/**

*

*  Mapper 接口

*

*

* @author elite

* @since 2022-09-11

*/

@Mapper

public interface AccountMapper extends BaseMapper {

   /**

    * 更新账户余额

    * @param user_id

    * @param amt

    * @return

    */

   @Update("UPDATE seata_account.account SET  acc_money= acc_money - #{amt} WHERE user_id = #{user_id} and (acc_money - #{amt}) >= 0")

   boolean deductAcct(Integer user_id, BigDecimal amt);

}

启动账户

e08de4292fc942fa8ea0024073988d84.png

库存模块

mapper

/**

*

* 库存表 Mapper 接口

*

*

* @author elite

* @since 2022-09-11

*/

@Mapper

public interface StockMapper extends BaseMapper {

   @Update("UPDATE seata_stock.stock set stock_num = stock_num - #{product_num} WHERE product_id = #{product_id} and  (stock_num - #{product_num}) >= 0")

   boolean deuctStock(Integer product_id, Integer product_num);

}

启动账户模块

d0203907876c4b048224ac46fd593a5f.png

订单模块

依赖

 

 

      com.alibaba.cloud

      spring-cloud-alibaba-seata

      2.2.0.RELEASE

 

 

yml配置

server:

 port: 8087

spring:

 application:

   name: springcloud-seata-order

 ##nacos服务地址注册

 cloud:

   nacos:

     discovery:

       server-addr: 192.168.5.130:8848

       enabled: true

   alibaba:

     seata:

       tx-service-group: springcloud-seata-order

 #配置数据库

 datasource:

   type: com.alibaba.druid.pool.DruidDataSource

   url: jdbc:mysql://192.168.5.130:3306/seata_order

   driver-class-name: com.mysql.jdbc.Driver

   username: root

   password: 123456

   druid:

     # 初始化大小,最小,最大

     initialSize: 5

     minIdle: 5

     maxActive: 20

     # 配置获取连接等待超时的时间(毫秒)

     maxWait: 60000

     # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

     timeBetweenEvictionRunsMillis: 60000

     # 配置有一个连接在连接池中的最小生存时间,单位是毫秒

     minEvictableIdleTimeMillis: 300000

     validationQuery: SELECT 1 FROM DUAL

     testWhileIdle: true

     testOnBorrow: false

     testOnReturn: false

     # 打开PSCache,指定每个连接上PSCache的大小

     poolPreparedStatements: true

     maxPoolPreparedStatementPerConnectionSize: 20

     # 配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙

     filters: stat, wall, log4j

     # 通过connectProperties属性来打开mergeSql功能,慢SQL记录

     connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

#mybatis日志

mybatis-plus:

 configuration:

   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

 mapper-locations: classpath:mapper/*.xml

controller类

/**

* <p>

* 订单表 前端控制器

* </p>

*

* @author elite

* @since 2022-09-11

*/

@RestController

@RequestMapping("/springcloud/order")

public class OrderController {

   @Autowired

   IOrderService orderService;

   /**

    * 传入用户id 商品id下单

    * @param product_id

    * @param user_id

    * @return

    */

   @GetMapping("/createOrder/{product_id}/{user_id}/{product_num}")

   public R createOrder(@PathVariable("")Integer product_id,

                        @PathVariable("user_id") Integer user_id,

                        @PathVariable("product_num")Integer product_num){

        R r = orderService.createOrder(product_id,user_id,product_num);

       return r;

   }

}

服务类

 

/**

* <p>

* 订单表 服务实现类

* </p>

*

* @author elite

* @since 2022-09-06

*/

@Service

@Slf4j

public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

   @Autowired

   OrderMapper orderMapper;

   //库存服务

   @Autowired

   StockService stockService;

   //账户服务

   @Autowired

   AcctService acctService;

   /**

    * 下单服务

    * @param product_id

    * @param user_id

    * @return

    */

   @GlobalTransactional

   @Override

   public R createOrder(Integer product_id, Integer user_id,Integer product_num) {

       //库存服务:对给定的商品扣除仓储数量。

       Product product = stockService.getProductById(product_id);

       if (product == null){

           return R.fail(400,"商品信息为空,商品ID不能为空");

       }

       boolean deductSuccess = stockService.deductStock(product_id, product_num);

       if (!deductSuccess){

           return R.fail(400,"扣减库存失败!");

       }

       //验证用户

       User user = acctService.getUserByUseId(user_id);

       if (user == null){

           return R.fail(400,"传入的用户ID不存在");

       }

       //订单服务:根据采购需求创建订单。

       BigDecimal amt = (product.getProductPrice()).multiply(new BigDecimal(product_num  ));

       //订单信息

       Order order = new Order();

       order.setOrderNo(10);

       order.setProductId(product_id);

       order.setUserId(user.getUserId());

       order.setOrderNum(product_num);

       order.setOrderAmt(amt); //单价*数量

       order.setOrderStatus("下单");

       order.setPayStatus("支付成功");

       order.setCreateBy("牛奶糖");

       order.setUpdateBy("牛奶糖");

       orderMapper.insert(order);

       //模拟异常

       //int i = 1/0;

       //帐户服务:从用户帐户中扣除余额。

       boolean deductAcctFlag = acctService.deductAcct(user_id, amt);

       if (!deductAcctFlag){

           return R.fail(400,"扣减账户失败!");

       }

       return R.ok(200,"下单成功!",order);

   }

}

测试库存模块

获取商品

93c9f49a5c53426a8733e51689a79fe7.png

扣减库存

4ff1892826de405ea1cf0b6d8243f586.png


执行的sql

==> Preparing: UPDATE seata_stock.stock set stock_num = stock_num - ? WHERE product_id = ? and (stock_num - ?) >= 0

aabc06ec857940548bad1a3f7c3738c0.png


测试账户模块

获取用户

111422df41f74fb7bafea5c933110be7.png

相关文章
|
2月前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
2月前
|
存储 Java Nacos
Spring Cloud+Nacos+KMS 动态配置最佳实践
本文讲述了 Spring Cloud 应用中结合 Nacos 实现了运行期配置动态更新的功能,以及在此基础上结合 KMS 在不改动代码的情况下对应用使用的敏感配置进行保护,解决将配置迁移到 Nacos 中可能存在的数据安全顾虑,并对其底层工作原理做了简单介绍。
501 17
|
25天前
|
消息中间件 SQL 中间件
大厂都在用的分布式事务方案,Seata+RocketMQ带你打破10万QPS瓶颈
分布式事务涉及跨多个数据库或服务的操作,确保数据一致性。本地事务通过数据库直接支持ACID特性,而分布式事务则需解决跨服务协调难、高并发压力及性能与一致性权衡等问题。常见的解决方案包括两阶段提交(2PC)、Seata提供的AT和TCC模式、以及基于消息队列的最终一致性方案。这些方法各有优劣,适用于不同业务场景,选择合适的方案需综合考虑业务需求、系统规模和技术团队能力。
177 7
|
2月前
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
81 6
|
2月前
|
数据库
如何在Seata框架中配置分布式事务的隔离级别?
总的来说,配置分布式事务的隔离级别是实现分布式事务管理的重要环节之一,需要认真对待和仔细调整,以满足业务的需求和性能要求。你还可以进一步深入研究和实践 Seata 框架的配置和使用,以更好地应对各种分布式事务场景的挑战。
43 6
|
2月前
|
消息中间件 运维 数据库
Seata框架和其他分布式事务框架有什么区别
Seata框架和其他分布式事务框架有什么区别
35 1
|
3月前
|
JSON SpringCloudAlibaba Java
Springcloud Alibaba + jdk17+nacos 项目实践
本文基于 `Springcloud Alibaba + JDK17 + Nacos2.x` 介绍了一个微服务项目的搭建过程,包括项目依赖、配置文件、开发实践中的新特性(如文本块、NPE增强、模式匹配)以及常见的问题和解决方案。通过本文,读者可以了解如何高效地搭建和开发微服务项目,并解决一些常见的开发难题。项目代码已上传至 Gitee,欢迎交流学习。
197 1
Springcloud Alibaba + jdk17+nacos 项目实践
|
3月前
|
负载均衡 算法 Java
蚂蚁面试:Nacos、Sentinel了解吗?Springcloud 核心底层原理,你知道多少?
40岁老架构师尼恩分享了关于SpringCloud核心组件的底层原理,特别是针对蚂蚁集团面试中常见的面试题进行了详细解析。内容涵盖了Nacos注册中心的AP/CP模式、Distro和Raft分布式协议、Sentinel的高可用组件、负载均衡组件的实现原理等。尼恩强调了系统化学习的重要性,推荐了《尼恩Java面试宝典PDF》等资料,帮助读者更好地准备面试,提高技术实力,最终实现“offer自由”。更多技术资料和指导,可关注公众号【技术自由圈】获取。
蚂蚁面试:Nacos、Sentinel了解吗?Springcloud 核心底层原理,你知道多少?
|
6天前
|
存储 网络协议 Nacos
高效搭建Nacos:实现微服务的服务注册与配置中心
Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一款动态服务发现、配置管理和服务管理平台。它旨在帮助开发者更轻松地构建、部署和管理分布式系统,特别是在微服务架构中。
153 81
高效搭建Nacos:实现微服务的服务注册与配置中心
|
22天前
|
JSON Java Nacos
SpringCloud 应用 Nacos 配置中心注解
在 Spring Cloud 应用中可以非常低成本地集成 Nacos 实现配置动态刷新,在应用程序代码中通过 Spring 官方的注解 @Value 和 @ConfigurationProperties,引用 Spring enviroment 上下文中的属性值,这种用法的最大优点是无代码层面侵入性,但也存在诸多限制,为了解决问题,提升应用接入 Nacos 配置中心的易用性,Spring Cloud Alibaba 发布一套全新的 Nacos 配置中心的注解。
136 12

热门文章

最新文章