IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 分布式事务 -> 正文阅读

[大数据]分布式事务

目录

Seata AT事务

TC事务协调器

业务模块中添加Seata AT事务

Seata TCC事务

TCC - 两个阶段的三种操作

业务模块中添加Seata TCC事务


Seata AT事务

TC事务协调器

1.从seata官网下载事务协调器服务

2.配置:

  • ?? - seata/conf/registry.conf -- 连接 eureka,向注册表注册
  • ?? - seata/conf/file.conf -- 协调器运行期间记录的日志数据的存储位置
  • ?? - seata/bin/seata-server.bat -- 设置 JVM 使用的内存大小

3.在bin目录下cmd打开dos窗口,运行seata-server.bat

- 必须用JDK1.8

- 命令窗口不能关闭

- 命令窗口不能选中,否则应用会被挂起,暂停执行

业务模块中添加Seata AT事务

1.添加seata依赖

<!--seata 依赖有自动配置
    如果不添加其他 Seata配置文件,项目无法启动
-->
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-alibaba-seata</artifactId>
  <version>2.0.0.RELEASE</version>
  <exclusions>
    <exclusion>
      <artifactId>seata-all</artifactId>
      <groupId>io.seata</groupId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>io.seata</groupId>
  <artifactId>seata-all</artifactId>
  <version>1.3.0</version>
</dependency>

2.三个配置:

  • ?? - application.yml -- 事务组的组名
spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: order_tx_group # 事务组组名
  • ?? - registry.conf -- 设置注册中心的地址
  • ?? - file.conf -- 事务组对用使用哪个协调器
service {
  #transaction service group mapping
  # order_tx_group 与 yml 中的 “tx-service-group: order_tx_group” 配置一致
  # “seata-server” 与 TC 服务器的注册名一致
  # 从eureka获取seata-server的地址,再向seata-server注册自己,设置group
  vgroupMapping.order_tx_group = "seata-server"
  #only support when registry.type=file, please don't set multiple addresses
  order_tx_group.grouplist = "127.0.0.1:8091"
  #degrade, current not support
  enableDegrade = false
  #disable seata
  disableGlobalTransaction = false
}

3.自定义自动配置类,创建数据源代理对象

- AT事务的自动事务控制代码,都是由数据源代理对象提供的

package cn.tedu.order;

import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/*
自定义自动配置类,创建原始数据源和数据源代理对象
 */
@Configuration
public class DSConf {
    // 原始数据源
    @ConfigurationProperties(prefix = "spring.datasource")  //将配置文件中的数据库参数注入HikariDataSource对象
    @Bean
    public DataSource DataSource(){
        return new HikariDataSource();
    }
    // Seata AT事务的数据源代理对象
    @Primary  //首选对象
    @Bean
    public DataSource dataSourceProxy(DataSource ds){
        return new DataSourceProxy(ds);
    }
}

4.排除springboot默认的数据源自动配置

在启动类中添加以下注解:

//排除默认的数据源配置,应用自定义的自动配置类
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

5.业务方法上添加事务注解

?? - `@Transactional` - 控制本地事务
?? - `@GlobalTransactional` - 创建 TM,启动全局事务,只在第一个模块添加

Seata TCC事务

TCC 是一种有侵入的事务方案

- 所有事务控制代码都需要自己实现
- 底层的数据库、业务代码都需要修改

有些复杂情况下,AT事务无法实现自动事务控制,就需要手动控制事务的方案

TCC - 两个阶段的三种操作

- 第一个阶段

? Try - 预留资源、冻结数据

- 第二阶段

? - Confirm - 确认、提交,使用一阶段冻结的数据实现业务数据处理
? - Cancel - 取消、回滚,把一阶段冻结的数据恢复回去

业务模块中添加Seata TCC事务

1.添加seata依赖

2.三个配置文件

  • ?? - application.yml -- 组名
  • ?? - registry.conf -- eureka地址
  • ?? - file.conf -- 事务组对应使用的协调器

3.修改Mapper,添加新的TCC三个数据库操作

4.按照Seata TCC的规则,添加TccAction接口和实现类,实现三个操作的方法

接口

package cn.tedu.order.tcc;

import io.seata.rm.tcc.api.BusinessActionContext;
import io.seata.rm.tcc.api.BusinessActionContextParameter;
import io.seata.rm.tcc.api.LocalTCC;
import io.seata.rm.tcc.api.TwoPhaseBusinessAction;

import java.math.BigDecimal;

/*
在接口中要定义 TCC 三个方法
 */
@LocalTCC
public interface OrderTccAction {
    /*
    BusinessActionContext上下文对象,用来从第一阶段向第二阶段传递数据
    第一阶段需要业务数据参数用来冻结业务数据,
    为了避开seata的一个bug,最好不传递封装的对象,而是把数据打散一个个的单独传递

    第一阶段方法需要在业务代码中手动调用
     */
    @TwoPhaseBusinessAction(name = "OrderTccAction",    //指定第一阶段方法
                            commitMethod = "commit",    //指定Confirm方法
                            rollbackMethod = "rollback")//指定Cancel方法
    boolean prepare(BusinessActionContext ctx,
                    @BusinessActionContextParameter(paramName = "orderId") Long id,
                    Long userId, Long productId, Integer count, BigDecimal money);      //T - Try
    /*
    第二阶段方法由RM(资源管理器)接收TC的二阶段指令,执行二阶段方法
     */
    boolean commit(BusinessActionContext ctx);       //C - Confirm
    boolean rollback(BusinessActionContext ctx);     //C - Cancel
}

实现类

package cn.tedu.order.tcc;

import cn.tedu.order.entity.Order;
import cn.tedu.order.mapper.OrderMapper;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Component
public class OrderTccActionImpl implements OrderTccAction {
    @Autowired
    private OrderMapper orderMapper;

    @Override
    @Transactional
    public boolean prepare(BusinessActionContext ctx, Long id, Long userId, Long productId, Integer count, BigDecimal money) {
        orderMapper.createFrozen(new Order(id,userId,productId,count,money,0));
        return true;    //第一阶段冻结成功
    }

    @Override
    @Transactional
    public boolean commit(BusinessActionContext ctx) {
        //第一阶段向第二阶段传递上下文对象时,先转成json进行传递,会丢失数据的类型信息
        Long orderId = Long.valueOf(ctx.getActionContext("orderId").toString());
        orderMapper.updateStatus(orderId, 1);//订单状态改成1,正常状态
        return true;    //确认提交成功
    }

    @Override
    @Transactional
    public boolean rollback(BusinessActionContext ctx) {
        Long orderId = Long.valueOf(ctx.getActionContext("orderId").toString());
        orderMapper.deleteById(orderId);
        return true;//取消回滚成功
    }
}

5.调整业务方法,不直接完成业务,而是调用第一阶段方法冻结数据

tcc.prepare(null,order.getId(),order.getUserId(),
        order.getProductId(),order.getCount(),order.getMoney());

6.在第一个模块的业务方法上添加`@GlobalTransactional`

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 22:59:51  更:2021-12-28 23:01:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 13:46:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码