微服务系列:分布式事务 Spring Cloud Alibaba 之 Seata 实战篇

本文详细介绍了如何在实际项目中使用Seata进行分布式事务管理。通过创建订单、库存和账户三个服务,展示了在Spring Cloud Alibaba框架下,如何利用Seata的AT模式解决跨数据库和远程调用的事务问题。文章包含每个服务的搭建步骤、核心代码展示以及各种场景的测试,包括正常下单、库存不足和用户余额不足的情况。

这篇中我们就要项目实战中来使用 Seata 了,毕竟学习它就是为了实战中使用的。

其实 Seata 使用起来很简单,主要就是使用 @GlobalTransactional注解,但是搭建过程却还是稍微有点复杂的。

话不多说,开始今天的学习。

一、前言

  • 本案例使用的是 Seata 的 AT 模式
  • 由于篇幅有限,本文只贴出核心代码和配置,完整代码地址:cloud-seata: seata demo - Gitee.com
  • 本案例使用 Nacos 作为注册中心,使用 Nacos 作为配置中心

1. 版本说明

  • MySQL 8.0.27
  • Nacos Server 2.0.3
  • Seata Server 1.4.2
  • Spring Boot 2.3.7.RELEASE
  • Spring Cloud Hoxton.SR9
  • Spring Cloud Alibaba 2.2.5.RELEASE

2. 案例目标

本案例将会创建三个服务,分别是订单服务、库存服务、账户服务,各服务之间的调用流程如下:

  • 1)当用户下单时,调用订单服务创建一个订单,然后通过远程调用(OpenFeign)让库存服务扣减下单商品的库存
  • 2)订单服务再通过远程调用(OpenFeign)让账户服务来扣减用户账户里面的余额
  • 3)最后在订单服务中修改订单状态为已完成

上述操作跨越了三个数据库,有两次远程调用,很明显会有分布式事务的问题,项目的整体结构如下:

cloud-seata
├── seata-account     # 账户模块,端口:9201
├── seata-order       # 订单模块,端口:9211
└── seata-product     # 库存模块,端口:9221
复制代码

二、代码

1. 账户服务搭建

创建 seata-account 服务模块

1.1、创建数据库

# 账户数据库信息 seata_account
DROP DATABASE IF EXISTS seata_account;
CREATE DATABASE seata_account;
​
DROP TABLE IF EXISTS seata_account.account;
CREATE TABLE seata_account.account
(
    id               INT(11) NOT NULL AUTO_INCREMENT,
    balance          DOUBLE   DEFAULT NULL,
    last_update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4;
​
DROP TABLE IF EXISTS seata_account.undo_log;
CREATE TABLE seata_account.undo_log
(
    id            BIGINT(20) NOT NULL AUTO_INCREMENT,
    branch_id     BIGINT(20) NOT NULL,
    xid           VARCHAR(100) NOT NULL,
    context       VARCHAR(128) NOT NULL,
    rollback_info LONGBLOB     NOT NULL,
    log_status    INT(11) NOT NULL,
    log_created   DATETIME     NOT NULL,
    log_modified  DATETIME     NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY ux_undo_log (xid, branch_id)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4;
INSERT INTO seata_account.account (id, balance)
VALUES (1, 50);
复制代码

其中,库中的undo_log表,是Seata AT模式必须创建的表,主要用于分支事务的回滚。 另外,考虑到测试方便,我们插入了一条id = 1account记录。

1.2、添加依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
        </exclusion>
        <exclusion>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
        </exclusion>
    </exclusions>
</dependency>
​
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>1.4.2</version>
</dependency>
​
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.4.2</version>
</dependency>
复制代码

由于使用的SpringCloud Alibaba依赖版本是2.2.5.RELEASE,其中自带的 seata 版本是1.3.0,但是我们 Seata 服务端使用的版本是 1.4.2,因此需要排除原有的依赖,重新添加 1.4.2 的依赖。

如果依赖版本不一致,启动后会报如下错误

no available service 'null' found, please make sure registry config correct

注意:seata 客户端的依赖版本必须要和服务端一致。

1.3、服务配置文件

server:
  port: 9201
​
# spring配置
spring:
  application:
    name: seata-account
  datasource:
    druid:
      username: r
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值