分布式之事务tx-lcn

目录

分布式事务tx-lcn

一、分布式事务介绍

二、tx-lcn框架介绍

三、Tx-LCN之lcn模式实践demo

1、demo环境

2、搭建说明

3、搭建tx-manager服务

4、使用分布式事务


分布式事务tx-lcn

tc-lcn官网:https://www.txlcn.org/zh-cn/index.html

一、分布式事务介绍

 目前分布式事务存在两大理论依据:CAP定律 BASE理论。

CAP定律:指的是在一个分布式系统中、Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。

     一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)

     可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)

     分区容错性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

BASE理论:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。

二、tx-lcn框架介绍

1、版本介绍:LCN框架在2017年6月份发布第一个版本,从开始的1.0,已经发展到了5.0版本。5.0以后由于框架兼容了LCN、TCC、TXC三种事务模式,为了避免区分LCN模式,特此将LCN分布式事务改名为TX-LCN分布式事务框架

2、框架定位:本身并不操作事务,而是基于对本地事务的协调从而达到事务一致性的效果。

3、tx-lcn原理:TX-LCN由TxClient、TxManager两大模块组成。TxManager作为分布式事务的控制方。事务发起方或者参与反都由TxClient端来控制。

              ①事务发起方,创建事务组到TxManager;参与方分别加入事务组;

              ②参与方通知TxManager都准备好了,再一次通知参与方执行事务。按照执行顺序通知。

              ③TxManager将事务结果返回给事务发起方。

原理图如下:

4、tx-lcn之lcn、tcc、txc模式对比

      lcn模式:①对代码的嵌入性为低。

                     ②事务的提交和回滚基于本地事务方控制,对数据一致性有较高的保障。

                     ③缺陷:代理的连接需要事务发起方一共释放连接,增加了连接占用的事件。

     tcc模式:

                 原理:不依赖资源管理器对XA的支持,而是通过对业务逻辑的调度来实现分布式事务,共分为三步:Try: 尝试执行业务、 Confirm:确认执行业务、 Cancel: 取消执行业务;

                   ①对代码的嵌入性高,要求每个业务需要写三种步骤的操作;

                   ②对有无本地事务控制都可以支持,使用面广。

                   ③数据一致性控制几乎完全由开发者控制,对业务开发难度要求高。

    txc模式:

                原理:在执行SQL之前,先查询SQL的影响数据,然后保存这些信息和创建锁。当需要回滚的时候,就采用这些记录数据回滚数据库,目前锁实现依赖redis分布式锁控制。

                  ①同样对代码的嵌入性低。

                  ②仅限于对支持SQL方式的模块支持。

                  ③由于每次执行SQL之前需要先查询影响数据,因此相比LCN模式消耗资源与时间要多。

                   ④不会占用数据库的连接资源。

 

三、Tx-LCN之lcn模式实践demo

1、demo环境

                jdk1.8 、springboot2.0.6、springcloud Finchley.SR1、redis3.2.100 、txlcn-tm 5.0.2.RELEASE

2、搭建说明

          需先搭建tx-manager服务,然后其他服务使用。

           springcloud环境之前已经搭建好,这里不再阐述。

3、搭建tx-manager服务

     ①建立数据库,库名为tx-manager

       创建表,导入下面的sql

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

   ③在启动类上添加注解

     @EnableTransactionManagerServer

   ④配置文件application.properties

    根据自己的实际情况修改,更多配置请参考官网http://www.txlcn.org/zh-cn/docs/setting/manager.html

#指定注册中心地址
eureka.client.serviceUrl.defaultZone= http://localhost:1010/eureka/
eureka.instance.instance-id=tx-manager
eureka.instance.prefer-ip-address=true

#服务端口
server.port=2030
#服务名
spring.application.name=tx-manager

#数据库配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tx-manager?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

#mybatis配置
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true

#TxManager配置
# TxManager Host Ip
tx-lcn.manager.host=127.0.0.1
# TxClient连接请求端口
tx-lcn.manager.port=8070
# 心跳检测时间(ms) 默认为 300000
tx-lcn.manager.heart-time=15000
# 分布式事务执行总时间 默认为36000
tx-lcn.manager.dtx-time=30000
#参数延迟删除时间单位ms
tx-lcn.message.netty.attr-delay-time=30000
tx-lcn.manager.concurrent-level=128
# TM后台登陆密码,默认值为codingapi
tx-lcn.manager.admin-key=codingapi

# 开启日志
tx-lcn.logger.enabled=true
logging.level.com.codingapi=debug

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

   ⑤测试服务

     安装完成,启动服务,访问tx-manager管理后台:http://localhost:7970/admin/index.html#/login
     类似注册中心,可以看到哪些服务需要做事务处理的。可以看到配置的信息,还有异常记录和错误日志。

    登录的默认密码为codingapi

4、使用分布式事务

      配置tc-client,就是自己需要使用的服务。注意:A服务调用B服务,那个A\B服务都需要做下面的配置。

       ①、导包

            <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>

     ②、开启微服务事务

启动类上加入注解 @EnableDistributedTransaction

    ③、application.properties配置

         添加tm-manager的服务地址

#默认是本机的8070端口,可以不写,可根据需要修改
tx-lcn.client.manager-address=127.0.0.1:8070

   ④、服务层添加注解

         如:A服务调用B服务    

  a服务:

       service层的方法上:@LcnTransaction        @Transactional

   //利用feign添加部门信息
    @Override
    @LcnTransaction //lcn的事务注解
    @Transactional  //本地事务注解
    public ResultVo addDepartment(Department department) {
        User user = new User("大娃","123456",26);
        userMapper.addUser(user);  //给本地添加数据
        systemManageClient.addDepartment(department);  //调取其他服务添加数据
        return ResultVo.ok();
    }

       b服务:

    lcn事务配饰说明:

RQUIRED:如果有事务就把这个操作加入事务中,如果没有事务就另外新建一个事务。如:增删改操作。
SUPPORTS:是有事务就把操作加入事务,没有事务也能脱离事务独立运行。如查询操作。

//添加部门
    @Override
    @LcnTransaction(propagation = DTXPropagation.SUPPORTS) 
    @Transactional
    public void addDepartment(Department department) {
        //System.out.println(1/0);//测试分布式事务,发生异常后,user服务还能不能添加进去
        departmentMapper.addDepartment(department);
    }

注意:如果通过feign 调用时,feign注解中加了fallbackFactory =xxx.class的话;在Fallback方法里面加上这个
DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());

@Component
public class SystemManageFallback implements SystemManageClient {
    @Override
    public ResultVo addDepartment(Department department) {
        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
        return ResultVo.fail("添加部门信息失败了");
    }
}

 

测试:当B服务失败后,发起方A的数据也会回滚。创建成功。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值