使用Spring Boot实现分布式事务

使用Spring Boot实现分布式事务

大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!

在微服务架构中,分布式事务是一个重要的概念,它用于确保在分布式系统中各个服务之间的数据一致性。分布式事务的实现相对复杂,因为它需要跨越多个服务、数据库或消息队列来维护数据的一致性。本文将详细介绍如何使用Spring Boot实现分布式事务,重点介绍如何使用Spring Cloud和Seata框架来管理分布式事务。

一、分布式事务的基本概念

分布式事务是指在多个不同的数据库或服务之间执行的事务操作,这些操作需要保证一致性和完整性。分布式事务通常通过两阶段提交(2PC)、三阶段提交(3PC)或TCC(Try-Confirm/Cancel)等协议来实现。

二、Seata简介

Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的一款分布式事务解决方案,提供了高效且易用的分布式事务服务。Seata支持AT、TCC、SAGA和XA等多种事务模式。

三、环境准备

JDK 8或以上版本
Maven 3或以上版本
MySQL数据库
Seata Server
四、创建Spring Boot项目

首先,我们使用Spring Initializr创建一个新的Spring Boot项目,并添加必要的依赖。

打开 Spring Initializr
输入项目信息:
Group: cn.juwatech
Artifact: spring-boot-seata
添加依赖:
Spring Web
Spring Data JPA
MySQL Driver
Seata Spring Boot Starter
点击“Generate”按钮生成项目并下载,然后解压项目文件。

  1. 在 src/main/resources 目录下创建 application.yml 配置文件,添加以下内容:
server:
  port: 8080

spring:
  application:
    name: spring-boot-seata
  datasource:
    url: jdbc:mysql://localhost:3306/seata_example
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

seata:
  enabled: true
  application-id: spring-boot-seata
  tx-service-group: my_test_tx_group

  

  1. 在 src/main/resources 目录下创建 seata.conf 配置文件,添加以下内容:
transport {
  type = "TCP"
  server = "NIO"
  heartbeat = "true"
  serialization = "seata"
  compressor = "none"
}

service {
  vgroupMapping.my_test_tx_group = "default"
  enableDegrade = false
  disableGlobalTransaction = false
}

client {
  rm {
    asyncCommitBufferLimit = 10000
    lock {
      retryTimes = 30
      retryInterval = 10
    }
    reportRetryCount = 5
    tableMetaCheckEnable = false
  }

  tm {
    commitRetryCount = 5
    rollbackRetryCount = 5
  }

  undo {
    dataValidation = true
    logSerialization = "jackson"
    onlyCareUpdateColumns = true
  }
}

support {
  spring {
    datasource-autoproxy = false
  }
}

  

六、编写业务逻辑

  1. 创建实体类 Order 和 Account
    package cn.juwatech.seata.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Order {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String userId;
        private String productId;
        private Integer count;
        private Double money;
    
        // getters and setters
    }
    

      

    package cn.juwatech.seata.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Account {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String userId;
        private Double balance;
    
        // getters and setters
    }
    

      

    1. 创建 OrderRepository 和 AccountRepository
      package cn.juwatech.seata.repository;
      
      import cn.juwatech.seata.entity.Order;
      import org.springframework.data.jpa.repository.JpaRepository;
      
      public interface OrderRepository extends JpaRepository<Order, Long> {
      }
      

        

      package cn.juwatech.seata.repository;
      
      import cn.juwatech.seata.entity.Account;
      import org.springframework.data.jpa.repository.JpaRepository;
      
      public interface AccountRepository extends JpaRepository<Account, Long> {
          Account findByUserId(String userId);
      }
      

        

      1. 创建服务类 OrderService 和 AccountService
        package cn.juwatech.seata.service;
        
        import cn.juwatech.seata.entity.Order;
        import cn.juwatech.seata.repository.OrderRepository;
        import io.seata.spring.annotation.GlobalTransactional;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.stereotype.Service;
        
        @Service
        public class OrderService {
        
            @Autowired
            private OrderRepository orderRepository;
        
            @GlobalTransactional(name = "my_test_tx_group", rollbackFor = Exception.class)
            public void createOrder(Order order) {
                orderRepository.save(order);
            }
        }
        

          

        package cn.juwatech.seata.service;
        
        import cn.juwatech.seata.entity.Account;
        import cn.juwatech.seata.repository.AccountRepository;
        import io.seata.spring.annotation.GlobalTransactional;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.stereotype.Service;
        
        @Service
        public class AccountService {
        
            @Autowired
            private AccountRepository accountRepository;
        
            @GlobalTransactional(name = "my_test_tx_group", rollbackFor = Exception.class)
            public void decreaseBalance(String userId, double amount) {
                Account account = accountRepository.findByUserId(userId);
                if (account != null && account.getBalance() >= amount) {
                    account.setBalance(account.getBalance() - amount);
                    accountRepository.save(account);
                } else {
                    throw new RuntimeException("Insufficient balance");
                }
            }
        }
        

        创建控制器 OrderController

        package cn.juwatech.seata.controller;
        
        import cn.juwatech.seata.entity.Order;
        import cn.juwatech.seata.service.AccountService;
        import cn.juwatech.seata.service.OrderService;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.web.bind.annotation.*;
        
        @RestController
        @RequestMapping("/orders")
        public class OrderController {
        
            @Autowired
            private OrderService orderService;
        
            @Autowired
            private AccountService accountService;
        
            @PostMapping("/create")
            public String createOrder(@RequestBody Order order) {
                orderService.createOrder(order);
                accountService.decreaseBalance(order.getUserId(), order.getMoney());
                return "Order created successfully";
            }
        }
        

          

        七、运行并验证

        启动 Spring Boot 应用程序,并验证分布式事务功能。

        运行 SpringBootSeataApplication 类,启动 Spring Boot 应用程序。
        使用 Postman 或其他工具发送 POST 请求到 http://localhost:8080/orders/create,请求体为

        {
            "userId": "1",
            "productId": "P1001",
            "count": 2,
            "money": 200.00
        }
        

          

        1. 检查 MySQL 数据库,验证订单和账户信息是否正确更新。

        通过以上步骤,我们成功地将 Spring Boot 应用与 Seata 集成,实现了分布式事务管理。Seata 提供了强大的分布式事务管理功能,使得在微服务架构中实现数据一致性变得更加容易和高效。

          

原文链接:https://blog.csdn.net/java666668888/article/details/140401681

请登录后发表评论

    没有回复内容