Seata+Nacos 配置

Seata 分布式事务+Nacos 注册配置中心(spring-cloud-alibaba-dependencies:2.2.5.RELEASE)
Seata client采用AT 事务模式
Seata server侧采用数据库模式

seata官网: https://seata.io/zh-cn/blog/download.html

预备工作

确保后台已经启动 Nacos 服务。如果您尚且不熟悉 Nacos 的基本使用的话,可先行参考 Nacos 快速入门。建议使用 Nacos 1.2.0 及以上的版本。

获取server服务

gitee: https://gitee.com/seata-io/seata/releases
github: https://github.com/seata/seata/releases

获取配置文件及数据库脚本

gitee: https://gitee.com/seata-io/seata/tree/develop/script
github: https://github.com/seata/seata/tree/develop/script

假设server服务解压缩地址:/Users/user/seata
配置文件及数据库脚本保存地址: /Users/user/script/


  1. 执行数据库脚本

在业务数据库中添加undo_log表,sql脚本在/Users/user/script//client/at/db/mysql.sql
新建seata数据库,sql脚本在/Users/user/script//server/db/mysql.sql

  1. 修改server配置文件
    2.1 修改/Users/user/seata/conf/file.conf
    在这里插入图片描述
    2.2 修改/Users/user/seata/registry.conf
    在这里插入图片描述
    在这里插入图片描述
    2.3 修改下载的配置文件/Users/user/script/conf(这个可以最后在nacos中修改)
    1.3.1
    在这里插入图片描述

  2. 向Nacos添加配置文件

    3.1 打开Nacos控制台,建议新建一个命名空间,因为这个配置文件太多太乱
    3.2 找到shell脚本,位置/Users/user/script/config-center/nacos/nacos-config.sh
    3.3 打开命令工具执行

    sh ${SEATAPATH} -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca -u username -w password
    
    SEATAPATH: 你的配置文件位置,上面的/Users/user/script/config-center/nacos/nacos-config.sh
    -h: nacos服务ip.
    -p: nacos服务端口号.
    -g: 想要的分组信息.
    -t: 第一步新建的命名空间.
    -u: nacos登录名.
    -w: nacos登录密码
    

    注意:

    如果执行shell后显示
    在这里插入图片描述
    表示config文件查找错误想要手动指定
    编辑模式打开nacos-config.sh 第97行 将( d i r n a m e " (dirname "(dirname"PWD")/config.txt 替换为config.txt文件的绝对路径后再执行shell.

    效果图:在这里插入图片描述

  3. 启动Seata server服务
    在/Users/user/seata下,创建logs存放日志文件.执行/Users/user/seata/bin/seata-server.sh脚本
    在这里插入图片描述
    nacos服务注册信息
    在这里插入图片描述

  4. nacos上的application.yml文件添加seata信息
    config与registry中的信息,是在2.2中设置的,config信息导入到哪里是在执行shell决定的

# Seata 分布式事务
seata:
  enabled: true
  #seata注册的服务名称
  application-id: seata-service
  #此处配置自定义的seata事务分组名称
  tx-service-group: my_test_tx_group
  #开启数据库代理
  enable-auto-data-source-proxy: true
  config:
    type: nacos
    nacos:
      #nacos地址
      server-addr: 127.0.0.1:8848
      #配置文件的命名空间
      namespace: d4c88b0f-8b0f-8b0f-8b0f-4332b0116b71
      #配置文件的分组名
      group: SEATA_GROUP
      username: nacos
      password: nacos
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      #注册服务的命名空间
      namespace: d4c88b0f-8b0f-8b0f-8b0f-4332b0116b71
      #注册服务的名称
      application: seata-server
      #注册服务的分组名
      group: sds-cloud-01
      username: nacos
      password: nacos
  1. 修改pom文件
<!--注意:seata-spring-boot-starter包不具备xid传递功能-->
<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
   <version>2.2.5.RELEASE</version>
</dependency>
  1. 修改代码(模拟下单:销库存-下单-扣款)
	//demo.java
 	@GlobalTransactional//开启全局事务
    public ReturnModel placeOrder(int userId, int productId, int num) {
        System.out.println("xid======" + RootContext.getXID());
        //判断库存 并消减库存
        ReturnModel model = productApi.deduct(productId, num);
        if (!model.success()) {
            throw new RuntimeException(model.toJson());
        }
        //创建订单
        model = orderApi.create(userId, productId, Integer.valueOf(model.getData().toString()), num);
        if (!model.success()) {
            throw new RuntimeException(model.toJson());
        }
        return model;
    }
    
	//product.java
    public ReturnModel deduct(@RequestParam("productId") int productId,
                              @RequestParam("num") int num) {
        System.out.println("xid======" + RootContext.getXID());

        Product product = getById(productId);
        if (product == null) {
            return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("产品已下架");
        }
        if (product.getNum() < num) {
            return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("库存不足");
        }
        int price = product.getPrice();
        num = product.getNum() - num;
        boolean update = productService.update(new LambdaUpdateWrapper<Product>().set(Product::getNum, num).eq(Product::getId, productId));
        if (update) {
            return ReturnModel.create().data(price);
        }
        return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("库存失败");
    }

 	//order.java
    public ReturnModel create(int userId, int productId, int price, int num) {
        System.out.println("xid======" + RootContext.getXID());
        //创建订单
        Order order = new Order();
        order.setNum(num);
        order.setProductId(productId);
        order.setUserId(userId);
        order.setPrice(price * num);
        boolean save = save(order);
        if (!save) {
            return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("订单创建失败");
        }

        //扣款
        return userApi.debit(userId, order.getPrice());
    }

	//user.java
    public ReturnModel debit(@RequestParam("userId") int userId,
                             @RequestParam("price") int price) {
        System.out.println("xid======" + RootContext.getXID());

        User user = getById(userId);
        if (user == null) {
            return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("用户不存在");
        }
        if (user.getIntegral() < price) {
            return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("用户余额不足");
        }
        user.setIntegral(user.getIntegral() - price);
        boolean b = userService.updateById(user);
        if (b) {
            return ReturnModel.create();
        }
        return ReturnModel.create(ExceptionEnum.UNKNOWN_EXCEPTION).msg("扣款失败");
    }
  1. 请求链路图
    在这里插入图片描述
  2. Seata server 执行日志
    在这里插入图片描述

版权声明:本文为weixin_44937527原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。