LCN基本实现原理

1.发起方与参与方都与我们的LCN管理器一直保持长连接;
2.发起方在调用接口之前,先向LCN管理器申请一个全局的事务分组id;
3.发起方调用接口的时候在请求头中传递事务分组id;
4.参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前的事务。
5.发起方调用完接口后,如果出现异常的情况下,在通知给事务协调者回滚事务,这时候事务协调则告诉给参与方回滚当前的事务。

一、TM (服务端server )

官方文档:http://www.txlcn.org/zh-cn/docs/start.html

TM的准备环境

安装TM需要依赖的中间件: JRE1.8+, Mysql5.6+, Redis3.2+
如果需要手动编译源码, 还需要Git, Maven, JDK1.8+
创建MySQL数据库, 名称为: tx-manager

1、数据库准备 ( Redis自行准备)

  • 1、创建MySQL数据库, 名称为: tx-manager
  • 2、创建数据表
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(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

2 、获取源码启动TM(服务端)

源码下载,github地址:https://github.com/codingapi/tx-lcn修改TM配置信息

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_数据库


所有配置信息

spring.application.name=TransactionManager
server.port=7970

TM后台登陆密码

tx-lcn.manager.admin-key=lplb

JDBC 数据库配置

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://ip:3306/tx-manager?characterEncoding=UTF-8
spring.datasource.username=账号
spring.datasource.password=秘密

redis 的设置信息. 线上请用Redis Cluster

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=

TC连接IP, TM监听IP, 默认为 127.0.0.1, 如TM端和TC端不在同一PC/LINUX下,使用本机ip地址,(打包时请注意修改为服务器Ip地址)

tx-lcn.manager.host=192.168.177.134

TC连接端口,TM监听Socket端口, 默认为 ${server.port} - 100

tx-lcn.manager.port=8070

数据库方言

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

第一次运行可以设置为: create, 为TM创建持久化数据库表

spring.jpa.hibernate.ddl-auto=update

开启日志,默认为false

tx-lcn.logger.enabled=false
tx-lcn.logger.driver-class-name=分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_02{spring.datasource.url}
tx-lcn.logger.username=分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_03{spring.datasource.password}

心跳检测时间(ms). 默认为 300000

tx-lcn.manager.heart-time=300000

分布式事务执行总时间(ms). 默认为36000

tx-lcn.manager.dtx-time=8000

参数延迟删除时间单位ms 默认为dtx-time值

tx-lcn.message.netty.attr-delay-time=${tx-lcn.manager.dtx-time}

事务处理并发等级. 默认为机器逻辑核心数5倍

tx-lcn.manager.concurrent-level=160

分布式事务锁超时时间 默认为-1,当-1时会用tx-lcn.manager.dtx-time的时间

tx-lcn.manager.dtx-lock-time=${tx-lcn.manager.dtx-time}

雪花算法的sequence位长度,默认为12位.

tx-lcn.manager.seq-len=12

异常回调开关。开启时请制定ex-url

tx-lcn.manager.ex-url-enabled=false

事务异常通知(任何http协议地址。未指定协议时,为TM提供内置功能接口)。默认是邮件通知

#tx-lcn.manager.ex-url=/provider/email-to/*@.com


3、启动项目

idea 直接运行,访问:http://localhost:7970 密码为上一步配置文件中配置的 tx-lcn.manager.admin-key = lplb

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_ci_04


进入后

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_数据库_05

4、打 jar 包

添加打包配置信息,并注掉原来的所有打包配置

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_06


进入到txlcn-tm 目录, 打开cmd命令,运行命令 mvn clean package '-Dmaven.test.skip=true' 不要在idea中运行,idea中运行打包可能会报错

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_07

执行命令打包成功

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_数据库_08


直接运行即可 java -jar 包名

5、打 jar 包注意点

如果lcn ,的TM 端和 TC端 不在一个服务器, 需要配置为 TM 本机 ip地址

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_09

二、TC (客户端,spring-boot 整合使用 )

1、添加依赖

<!--  txlcn 分布式事务管理   -->
        <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>

如遇到错误: com.google.common.collect.FluentIterable.concat(Ljava/lang/Iterable;Ljava/la
排除 guava

<exclusions>
                <exclusion>
                    <artifactId>guava</artifactId>
                    <groupId>com.google.guava</groupId>
                </exclusion>
      </exclusions>
<!-- 去除 guava 依赖后的 -->
 <dependency>
 <groupId>com.codingapi.txlcn</groupId>
 <artifactId>txlcn-tc</artifactId>
 <version>5.0.2.RELEASE</version>
 <exclusions>
 <exclusion>
 <artifactId>guava</artifactId>
 <groupId>com.google.guava</groupId>
 </exclusion>
 </exclusions>
 </dependency>
 <dependency>
 <groupId>com.codingapi.txlcn</groupId>
 <artifactId>txlcn-txmsg-netty</artifactId>
 <version>5.0.2.RELEASE</version>
 <exclusions>
 <exclusion>
 <artifactId>guava</artifactId>
 <groupId>com.google.guava</groupId>
 </exclusion>
 </exclusions>
 </dependency>

2、启动类添加注解 @EnableDistributedTransaction

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_ci_10

3、添加 yml 连接server 端配置

配置连接地址

tx-lcn:
  client:
    manager-address: 127.0.0.1:8070
  logger:
    enabled: true

4、服务启动可在TM 查看服务

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_11

5、事务使用

tx-lcn 分布式事务管理, 参与方与发起方都需要加上注解

@LcnTransaction

@Transactional

发起方

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_spring_12


参与方

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_ci_13

6、tx-lcn 源码核心入口

  • 重写feign客户端拦截器 RequestInterceptor
  • Aop的重学的入口TransactionAspect
  • 实现该接口可以在请求之前处理参数SpringTracingApplier

7、lcn处理逻辑

----- 1、Lcn如何判断自己是发起方还是参与方?
根据当前的线程threadlocal中获取事务分组id,如果能够成功获取到则是为参与方,没有能够获取到就是为发起方。
------2、A调用B,B调用C 到底会生产几次事务id?

A调用 B 调用C 调用D 只有全局的分组的id 都是有一个局部的事务id

------3、参与方如何从请求头中获取事务id?如何加入事务组中?

入口 @LcnTransaction 必须有AOP才能够对我们注解生效。

LCN基本实现原理

1.发起方与参与方都与我们的LCN管理器一直保持长连接;
2.发起方在调用接口之前,先向LCN管理器申请一个全局的事务分组id;
3.发起方调用接口的时候在请求头中传递事务分组id;
4.参与方获取到请求头中有事务分组的id的,则当前业务逻辑执行完实现假关闭,不会提交或者回滚当前的事务。
5.发起方调用完接口后,如果出现异常的情况下,在通知给事务协调者回滚事务,这时候事务协调则告诉给参与方回滚当前的事务。

一、TM (服务端server )

官方文档:http://www.txlcn.org/zh-cn/docs/start.html

TM的准备环境

安装TM需要依赖的中间件: JRE1.8+, Mysql5.6+, Redis3.2+
如果需要手动编译源码, 还需要Git, Maven, JDK1.8+
创建MySQL数据库, 名称为: tx-manager

1、数据库准备 ( Redis自行准备)

  • 1、创建MySQL数据库, 名称为: tx-manager
  • 2、创建数据表
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(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

2 、获取源码启动TM(服务端)

源码下载,github地址:https://github.com/codingapi/tx-lcn修改TM配置信息

分布式事务LCN -- TM (服务端server ) + TC ( 客户端-spring-boot 使用)环境搭建及使用_数据库


所有配置信息

spring.application.name=TransactionManager
server.port=7970