快速玩转Dubbo生态之一致性事务篇(Seata)

简介: 本场景将对Dubbo接入一致性事务的方式进行介绍,带您体验快速上手Dubbo接入Seata生态。

快速玩转Dubbo生态之一致性事务篇(Seata)


1. 创建实验资源

开始实验之前,您需要先创建ECS实例资源。

1. 在实验室页面,单击创建资源

2. (可选)在实验室页面左侧导航栏中,单击云产品资源列表,可查看本次实验资源相关信息(例如IP地址、用户信息等)。

说明:资源创建过程需要1~3分钟。

2. Seate背景知识架构详解

本步骤为背景知识学习,详解Seate架构。

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

3. Seata背景知识Demo示例架构说明

本步骤为背景知识学习,详解用户采购商品业务使用的微服务代码。

用户采购商品业务,整个业务包含3个微服务:

  • 库存服务: 扣减给定商品的库存数量。
public interface StorageService {
    /**
     * 扣除存储数量
     */
    void deduct(String commodityCode, int count);
}
  • 订单服务: 根据采购请求生成订单。
public interface OrderService {
    /**
     * 创建订单
     */
    Order create(String userId, String commodityCode, int orderCount);
}
  • 账户服务: 用户账户金额扣减。
public interface AccountService {
    /**
     * 从用户账户中借出
     */
    void debit(String userId, int money);
}

4. Seata背景知识Demo示例的主要的业务逻辑代码详解

本步骤为背景知识学习,详解Demo示例的主要的业务逻辑代码。

BusinessServiceImpl:实现采购功能

public class BusinessServiceImpl implements BusinessService {
    private StorageService storageService;
    private OrderService orderService;
    /**
     * 采购
     */
    public void purchase(String userId, String commodityCode, int orderCount) {
        // 扣除存储数量
        storageService.deduct(commodityCode, orderCount);
        // 创建订单
        orderService.create(userId, commodityCode, orderCount);
    }
}

StorageServiceImpl:实现扣减给定商品的库存数量的功能。

public class StorageServiceImpl implements StorageService {
    private JdbcTemplate jdbcTemplate;
    @Override
    public void deduct(String commodityCode, int count) {
        // 修改数据库:扣减存储数量
        jdbcTemplate.update("update storage_tbl set count = count - ? where commodity_code = ?",
                new Object[]{count, commodityCode});
    }
}

OrderServiceImpl:实现根据采购请求生成订单的功能。

public class OrderServiceImpl implements OrderService {
    private AccountService accountService;
    private JdbcTemplate jdbcTemplate;
    public Order create(String userId, String commodityCode, int orderCount) {
        // 计算金额
        int orderMoney = calculate(commodityCode, orderCount);
        // 用户账户中扣减金额
        accountService.debit(userId, orderMoney);
        // 修改数据库:新建订单
        final Order order = new Order();
        order.userId = userId;
        order.commodityCode = commodityCode;
        order.count = orderCount;
        order.money = orderMoney;
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(con -> {
            PreparedStatement pst = con.prepareStatement(
                    "insert into order_tbl (user_id, commodity_code, count, money) values (?, ?, ?, ?)",
                    PreparedStatement.RETURN_GENERATED_KEYS);
            pst.setObject(1, order.userId);
            pst.setObject(2, order.commodityCode);
            pst.setObject(3, order.count);
            pst.setObject(4, order.money);
            return pst;
        }, keyHolder);
        order.id = keyHolder.getKey().longValue();
        return order;
    }
}

AccountService:实现用户账户金额扣减的功能。

public class AccountServiceImpl implements AccountService {
    private JdbcTemplate jdbcTemplate;
    @Override
    public void debit(String userId, int money) {  
        // 修改数据库:用户账户中扣减金额      
        jdbcTemplate.update("update account_tbl set money = money - ? where user_id = ?", new Object[]{money, userId});
    }
}

5. Demo启动实践

本实验场景提供示例代码和相关环境,本步骤指导您如何快速启动示例。

  1. 依次执行如下命令,通过docker-compose启动Seata-Server和MySQL等。
cd /root/dubbo-samples/dubbo-samples-transaction/src/main/resources/docker
systemctl enable docker
systemctl start docker
docker-compose up
  1. 在实验页面右上角,单击图标,新建一个终端窗口二。

  1. 在终端窗口二中,执行如下maven命令,打包Demo工程。
cd /root/dubbo-samples/dubbo-samples-transaction/
mvn clean package

返回结果如下,表示打包成功。

  1. 在终端窗口二中,执行如下命令,启动AccountService。
cd /root/dubbo-samples/dubbo-samples-transaction/
java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboAccountServiceStarter

返回结果如下,表示AccountService启动成功。

  1. 在实验页面右上角,单击图标,新建一个终端窗口三。

  1. 在终端窗口三中,执行如下命令,启动OrderService。
cd /root/dubbo-samples/dubbo-samples-transaction/
java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboOrderServiceStarter

返回结果如下,表示OrderService启动成功。

  1. 在实验页面右上角,单击图标,新建一个终端窗口四。

  1. 执行如下命令,启动 StorageService。
cd /root/dubbo-samples/dubbo-samples-transaction/
java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboStorageServiceStarter

  1. 在实验页面右上角,单击图标,新建一个终端窗口五。

  1. 执行如下命令, 启动 StorageService。
cd /root/dubbo-samples/dubbo-samples-transaction/
java -classpath ./target/dubbo-samples-transaction-1.0-SNAPSHOT.jar org.apache.dubbo.samples.starter.DubboBusinessTester

6. Demo核心流程详解

修改业务代码。

此处仅仅需要一行注解 @GlobalTransactional 写在业务发起方的方法上,例如示例代码:

@GlobalTransactional
    public void purchase(String userId, String commodityCode, int orderCount) {
        ......
    }

安装数据库。

要求: MySQL (InnoDB 存储引擎)。

说明:在本场景的示例中3个微服务需要3个独立的数据库,但为了方便我们使用同一物理库并配置3个逻辑连接串。

需要更改以下dubbo-account-service.xml、dubbo-order-service.xml和dubbo-storage-service.xml文件中的数据库url、username和password。

<property name="url" value="jdbc:mysql://x.x.x.x:3306/xxx" />
    <property name="username" value="xxx" />
    <property name="password" value="xxx" />

为Seata创建undo_log表。undo_log此表用于Seata的AT模式。

-- 注意当 Seata 版本升级至 0.3.0+ 将由之前的普通索引变更为唯一索引。
CREATE TABLE `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,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

创建相关业务表。

DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  `money` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `money` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

启动Seata-Server服务。

下载Seata软件包,并将其解压缩。

Usage: sh seata-server.sh(for linux and mac) or cmd seata-server.bat(for windows) [options]
  Options:
    --host, -h
      The host to bind.
      Default: 0.0.0.0
    --port, -p
      The port to listen.
      Default: 8091
    --storeMode, -m
      log store mode : file、db
      Default: file
    --help
e.g.
sh seata-server.sh -p 8091 -h 127.0.0.1 -m file

实验地址:https://developer.aliyun.com/adc/scenario/1ab92d77e58445ae8e82678e89c1f12f

相关文章
|
5月前
|
开发者
seata事务问题之不回滚客户端如何解决
Seata是一款开源的分布式事务解决方案,旨在提供高效且无缝的分布式事务服务;在集成和使用Seata过程中,开发者可能会遇到不同的异常问题,本合集针对Seata常见异常进行系统整理,为开发者提供详细的问题分析和解决方案,助力高效解决分布式事务中的难题。
393 8
|
5月前
|
监控 数据库
在Seata中一张表使用了联合主键,在事务回滚时报异常,改为单个主键,就没有这个异常,如何解决?
在Seata中一张表使用了联合主键,在事务回滚时报异常,改为单个主键,就没有这个异常,如何解决?
|
5月前
|
Java 数据库连接 API
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)
108 0
|
5月前
|
开发框架 Java 数据库连接
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)(下)
分布式事物【XA强一致性分布式事务实战、Seata提供XA模式实现分布式事务】(五)-全面详解(学习总结---从入门到深化)
81 0
|
5月前
|
Dubbo 关系型数据库 MySQL
Seata常见问题之serviceA方法无法注册分支事务到Seata如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
|
5月前
|
Java 数据库连接 API
Seata异常捕获问题之回滚事务如何解决
Seata是一款开源的分布式事务解决方案,旨在提供高效且无缝的分布式事务服务;在集成和使用Seata过程中,开发者可能会遇到不同的异常问题,本合集针对Seata常见异常进行系统整理,为开发者提供详细的问题分析和解决方案,助力高效解决分布式事务中的难题。
493 9
|
5月前
|
SQL 监控 Java
Seata常见问题之报找不到全局事务可能已经完成如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
837 0
|
5月前
|
Dubbo 应用服务中间件 Apache
恭喜 Apache Dubbo 和 Nacos 荣获开放原子“2023年度生态开源项目”
恭喜 Apache Dubbo 和 Nacos 荣获开放原子“2023年度生态开源项目”
|
11月前
|
存储 SQL 中间件
微服务之分布式事务服务端搭建(seata 1.0以下版本)
微服务之分布式事务服务端搭建(seata 1.0以下版本)
51 1
微服务之分布式事务服务端搭建(seata 1.0以下版本)
|
存储 SQL Java