前言:
本博文是基于简化后的博主以前一个分布式项目来集成TX-LCN框架,该框架用到了一些spring boot 及spring cloud技术:Eureka、Feign等,这些不是本文的重点,对相关技术不太了解的伙伴请自行查询相关资料。下面重点讲解TX-LCN框架在spring boot中的使用。本文侧重与框架之间的整合,理论说明较少,相关理论小伙伴们可以查询相关资料
TX-LCN框架介绍:
1.背景
LCN框架在2017年6月份发布第一个版本,从开始的1.0,已经发展到了5.0版本。
LCN名称是由早期版本的LCN框架命名,在设计框架之初的1.0 ~ 2.0的版本时框架设计的步骤是如下,各取其首字母得来的LCN命名。
锁定事务单元(lock)
确认事务模块状态(confirm)
通知事务(notify)
5.0以后由于框架兼容了LCN、TCC、TXC三种事务模式,为了避免区分LCN模式,特此将LCN分布式事务改名为TX-LCN分布式事务框架。
2.框架定位
TX-LCN定位于一款事务协调性框架,框架其本身并不操作事务,而是基于对事务的协调从而达到事务一致性的效果。
3.控制原理
TX-LCN由两大模块组成, TxClient、TxManager,TxClient作为模块的依赖框架,提供TX-LCN的标准支持,TxManager作为分布式事务的控制方。事务发起方或者参与反都由TxClient端来控制。
原理图:
核心步骤
创建事务组
是指在事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。
加入事务组
添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息通知给TxManager的操作。
通知事务组
是指在发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager,TxManager将根据事务最终状态和事务组的信息来通知相应的参与模块提交或回滚事务,并返回结果给事务发起方。
spring boot 与 TX-LCN整合
本次是以博主以前搭建的一个分布式框架的简化版框架为基准来整合TX-LCN框架,由于是以以前的框架为基准,可能存在引入不必要的jar包情况,这一点请注意。
本次以支付交易系统最常见的数据更新场景为例:支付成功后回调,首先更新订单库中的订单状态,再更新账户库中的账户表金额。这个牵涉到两个库中的两个表,这个就涉及到分布式事务问题了
1.环境依赖
JDK 8+
Maven 3(可选的)
SpringBoot 2.1.2.RELEASE
SpringCloud Greenwich.RELEASE
Mysql5.7
Redis3.2
2.基础环境搭建
1.安装redis,主要用于分布式锁
2.创建数据库
创建 tx-manager数据库,创建表
CREATE TABLE hibernate_sequence (next_val bigint(20) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE t_tx_exception (id bigint(20) NOT NULL AUTO_INCREMENT,group_id varchar(64) DEFAULT NULL,unit_id varchar(32) DEFAULT NULL,mod_id varchar(128) DEFAULT NULL,transaction_state int(4) DEFAULT NULL,registrar smallint(4) DEFAULT NULL,remark varchar(4096) DEFAULT NULL,ex_state smallint(4) DEFAULT NULL COMMENT ‘0 未解决 1已解决’,create_time datetime DEFAULT NULL, PRIMARY KEY (id) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
创建txcln-demo数据库
创建表
CREATE TABLE t_demo (
id bigint(20) NOT NULL AUTO_INCREMENT,
kid varchar(45) DEFAULT NULL,
demo_field varchar(255) DEFAULT NULL,
group_id varchar(64) DEFAULT NULL,
unit_id varchar(32) DEFAULT NULL,
app_name varchar(128) DEFAULT NULL,
create_time datetime DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
创建数据库tx-logger
创建相关表
CREATE TABLE t_logger (
id bigint(20) NOT NULL AUTO_INCREMENT,
group_id varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
unit_id varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
tag varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
content varchar(1024) COLLATE utf8mb4_unicode_ci NOT NULL,
create_time varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
app_name varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (id) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
创建数据库order
创建相关表
CREATE TABLE t_order (
id int(11) NOT NULL AUTO_INCREMENT,
order_no varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
order_amout decimal(10,0) DEFAULT NULL,
status varchar(2) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
创建数据库account
创建相关表
CREATE TABLE account (
id int(11) NOT NULL AUTO_INCREMENT,
account_number varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
amount decimal(10,0) DEFAULT NULL,
status varchar(2) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
3.项目工程讲解
项目工程如下图:
如上图所示,本次整合用了六个工程:
1.base-parent
本工程为基础工程,就一个pom.xml文件,包含了可能用到的jar包maven配置
2.frame-eureka
本工程为注册中心,所有的业务服务注册到该工程服务
3.frame-tm
本工程为TX-LCN由两大模块中的TxManager模块,主要用于控制事务、协调事务
pom.xml配置
application.properties配置
spring.application.name=TransactionManager
server.port=7970
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tx-manager?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=update
#mybatis.configuration.map-underscore-to-camel-case=true
#mybatis.configuration.use-generated-keys=true
spring.jpa.hibernate.ddl-auto=validate
tx-lcn.manager.host=127.0.0.1
tx-lcn.manager.port=8070
tx-lcn.manager.heart-time=300000
tx-lcn.manager.dtx-time=8000
tx-lcn.message.netty.attr-delay-time={tx-lcn.manager.dtx-time}
tx-lcn.manager.seq-len=12
tx-lcn.manager.ex-url-enabled=false
tx-lcn.manager.ex-url=/provider/email-to/*@.com
tx-lcn.logger.enabled=true
tx-lcn.logger.enabled=false
tx-lcn.logger.driver-class-name={spring.datasource.url}
tx-lcn.logger.username={spring.datasource.password}
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
4.bus-order、bus-account、frame-gateway
以上工程为TX-LCN由两大模块中的TxClient模块,调用关系为:
frame-gateway->bus-order
frame-gateway->bus-account
三者的pom.xml配置类似,新增如下jar包配置
关键属性文件配置,application-ujued.properties
frame-gateway工程关键修改处
main启动增加相关注解,如图
实现方法增加相关注解
bus-order工程关键修改处
main启动增加相关注解,如图
实现方法增加相关注解
bus-account工程关键修改处
main启动增加相关注解,如图
实现方法增加相关注解
4.测试
测试之前
order数据库t_order表的订单状态为0,account数据库的account表的金额为100
如图
打开postman测试工具如图
flag不为1时表示不回滚,执行后结果如图
现在让order数据库的t_order表的状态回退到0,account数据库的account表金额回退到100,
再次打开postman,参数flag为1,让系统抛异常回滚,如图
如上图所示,两个库的数据均已回滚
5.工程资源下载
6.后续
tx-lcn是一个典型的两阶段提交的实现方式,存在一定的不足,所用的事务都基于TM的协调,如果TM有问题,基于它的分布式服务将无法使用。其次tx-lcn存在锁资源的问题,在一定程度上将影响系统性能。敬请期待我的下一篇文章,将在一定程度解决上述问题