分布式-分布式事务

**

分布式-分布式事务(接上篇 分布式-Ribbon 负载均衡

**

现象:当有服务A调用服务B的情况,如果 A或者B业务出错时,整个业务A和B都应该回滚,Transtional做不到这点

解决:引入第三方应用
方案:

1.二段提交(CanCommit,DoCommit):当A 调用B时,向第三方应用开启事务组,将A,B加入事务组,当发送业务出错时,第三方广播回滚命令至A,B,A,B事务回滚

2.三段提交(CanCommit、PreCommit、DoCommit):在二段提交的前提上,在DoCommit前面多一个PreCommit,协调者和参与者都引入了超时机制

3.TCC(Try、Confirm、Cancel):举个例子,A向着B转40,A向C转70,但是A只有100,当tyrCommoit时,A先扣除40到冻结金额,再扣除70到冻结金额时发现钱不够,,将冻结金额还给A,事务失败。

 TCC三个操作描述:
1)Try: 检测、预留资源;
2)Confirm: 业务系统执行提交;默认Confirm阶段是不会出错的,只要TRY成功,CONFIRM一定成功;
3)Cancel: 业务取消,预留资源释放;

TX-LCN框架介绍TX-LCN分布式事务框架,LCN并不生产事务,LCN只是本地事务的协调工,LCN是一个高性能的分布式事务框架,兼容dubbo、springcloud框架,支持RPC框架拓展,支持各种ORM框架、NoSQL、负载均衡、事务补偿

创建数据库tx-manager,数据库下创建表 t_tx_exception

CREATE TABLE `t_tx_exception`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `group_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `unit_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `mod_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `transaction_state` tinyint(4) NULL DEFAULT NULL,
  `registrar` tinyint(4) NULL DEFAULT NULL,
  `remark` varchar(4096) NULL DEFAULT  NULL,
  `ex_state` tinyint(4) NULL DEFAULT NULL COMMENT '0 未解决 1已解决',
  `create_time` datetime NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

创建第三方应用:

一:引入依赖

        <dependency>
            <groupId>com.codingapi.txlcn</groupId>
            <artifactId>txlcn-tm</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

二,配置:

spring.application.name=txlcn-tm
server.port=7970

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=validate

# TM后台登陆密码
tx-lcn.manager.admin-key=123456

tx-lcn.manager.host=127.0.0.1
tx-lcn.manager.port=8070

# 开启日志,默认为false
tx-lcn.logger.enabled=true
tx-lcn.logger.driver-class-name=${spring.datasource.driver-class-name}
tx-lcn.logger.jdbc-url=${spring.datasource.url}
tx-lcn.logger.username=${spring.datasource.username}
tx-lcn.logger.password=${spring.datasource.password}logging.level.com.codingapi.txlcn=DEBUG

#redis 主机
spring.redis.host=127.0.0.1
#redis 端口
spring.redis.port=6379
#redis 密码
spring.redis.password=

三,在启动类添加注解 @EnableTransactionManagerServer
四,访问后台 http://127.0.0.1:7970/admin/index.html
在这里插入图片描述
设置两个tc
第一个TC(之前的service-a):
1.引入依赖

<dependency>
    <groupId>com.codingapi.txlcn</groupId>
    <artifactId>txlcn-tc</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.codingapi.txlcn</groupId>
    <artifactId>txlcn-txmsg-netty</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>

2.添加配置:

# 是否启动LCN负载均衡策略(优化选项,开启与否,功能不受影响)
tx-lcn.ribbon.loadbalancer.dtx.enabled=true
# 默认之配置为TM的本机默认端口
tx-lcn.client.manager-address=127.0.0.1:8070
# 开启日志,默认为false
tx-lcn.logger.enabled=true
#mysql连接属性,直接填具体的就好
tx-lcn.logger.driver-class-name=${spring.datasource.driver-class-name}
tx-lcn.logger.jdbc-url=${spring.datasource.url}
tx-lcn.logger.username=${spring.datasource.username}
tx-lcn.logger.password=${spring.datasource.password}
logging.level.com.codingapi.txlcn=DEBUG

3.提供接口,书写service

    @LcnTransaction//分布式事务
    @Override
    public String txlcn(String exFlag) {
        //先调用本地服务,新增一个用户user PS:调用EntityManager的merge,传进去的实体字段是什么就保存什么
        TbUser tbUser = new TbUser();
        tbUser.setUsername("huanzi");
        tbUser.setPassword("123456");
        //持久化
        TbUser user = entityManager.merge(tbUser);
        System.out.println(user);

        //调用B服务,新增一个用户描述description
        TbDescription description1 = bFeign.txlcn(user.getId());
        System.out.println(description1);

        //根据标识,是否抛出异常
        if (StringUtils.isEmpty(exFlag)) {
            return "操作成功,请查看一下数据库验证!";
        } else {
            throw new RuntimeException("rollback transactional by exFlag");
        }
    }

4.在启动类上使用 @EnableDistributedTransaction

第二个TC(service-b)
配置信息跟第一个TC一样

提供消费接口,书写service

  @LcnTransaction//分布式事务
    @Override
    public TbDescription txlcn(Integer userId) {
        TbDescription tbDescription = new TbDescription();
        tbDescription.setUserId(userId);
        tbDescription.setDescription("服务B设置的描述");
        TbDescription merge = entityManager.merge(tbDescription);
        //B服务报错
        return merge;
    }

开启注册服务,消费者,提供者,第三方事务管理者
访问消费者接口
http://127.0.0.1:10081/txlcn?exFlag=test

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

访问接口:http://127.0.0.1:10081/txlcn

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

建表语句:
service-a 的tb_user:

CREATE TABLE `tb_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '表id',
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
  `created` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `description_id` int(11) NULL DEFAULT NULL COMMENT '关联详情id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 45 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户信息表' ROW_FORMAT = Compact;

service-b的tb_description:
CREATE TABLE tb_description (
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) NOT NULL,
description varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值