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配置信息
所有配置信息
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=${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}
# 心跳检测时间(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
进入后
4、打 jar 包
添加打包配置信息,并注掉原来的所有打包配置
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
进入到txlcn-tm 目录, 打开cmd命令,运行命令
mvn clean package '-Dmaven.test.skip=true'
不要在idea中运行,idea中运行打包可能会报错
执行命令打包成功
直接运行即可
java -jar 包名
5、打 jar 包注意点
如果lcn ,的TM 端和 TC端 不在一个服务器, 需要配置为 TM 本机 ip地址
二、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
3、添加 yml 连接server 端配置
配置连接地址
tx-lcn:
client:
manager-address: 127.0.0.1:8070
logger:
enabled: true
4、服务启动可在TM 查看服务
5、事务使用
tx-lcn 分布式事务管理, 参与方与发起方都需要加上注解
@LcnTransaction
@Transactional
发起方
参与方
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才能够对我们注解生效。