SpringCloud 分布式事务解决方案

目录

TX-LCN分布式事务框架
TX-LCN分布式事务框架#
随着互联化的蔓延,各种项目都逐渐向分布式服务做转换。如今微服务已经普遍存在,本地事务已经无法满足分布式的要求,由此分布式事务问题诞生。 分布式事务被称为世界性的难题,目前分布式事务存在两大理论依据:CAP定律 BASE理论。

官网地址:https://www.txlcn.org/zh-cn/

GitHun:https://github.com/yizhishang/tx-lcn/

在一个分布式系统下存在多个模块协调来完成一次业务。那么就存在一次业务事务下可能横跨多种数据源节点的可能。TX-LCN将可以解决这样的问题。

​ 例如存在服务模块A 、B、 C。A模块是mysql作为数据源的服务,B模块是基于redis作为数据源的服务,C模块是基于mongo作为数据源的服务。若需要解决他们的事务一致性就需要针对不同的节点采用不同的方案,并且统一协调完成分布式事务的处理。

img

方案:

​ 若采用TX-LCN分布式事务框架,则可以将A模块采用LCN模式、B/C采用TCC模式就能完美解决。

TX-LCN 主要有两个模块,Tx-Client(TC) Tx-Manager™. TC作为微服务下的依赖,TM是独立的服务。

安装TM需要依赖的中间件: JRE1.8+, Mysql5.6+, Redis3.2+
如果需要手动编译源码, 还需要Git, Maven, JDK1.8+

创建MySQL数据库, 名称为: tx-manager
创建数据表
Copy
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;
TM下载与配置#
从历史版本TM下载找到5.0.2.RELEASE的TM, 下载.
修改配置信息
Copy
spring.application.name=tx-manager
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
spring.datasource.username=root
spring.datasource.password=root
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true

TxManager Host Ip

tx-lcn.manager.host=127.0.0.1

TxClient连接请求端口

tx-lcn.manager.port=8070

心跳检测时间(ms)

tx-lcn.manager.heart-time=15000

分布式事务执行总时间

tx-lcn.manager.dtx-time=30000
#参数延迟删除时间单位ms
tx-lcn.message.netty.attr-delay-time=10000
tx-lcn.manager.concurrent-level=128

TM后台登陆密码,默认值为codingapi

tx-lcn.manager.admin-key=123456
logging.level.com.codingapi=debug
#redis 主机
spring.redis.host=127.0.0.1
#redis 端口
spring.redis.port=6379
#redis 密码
spring.redis.password=

开启日志,默认为false

tx-lcn.logger.enabled=true
tx-lcn.logger.driver-class-name= s p r i n g . d a t a s o u r c e . d r i v e r − c l a s s − n a m e t x − l c n . l o g g e r . j d b c − u r l = {spring.datasource.driver-class-name} tx-lcn.logger.jdbc-url= spring.datasource.driverclassnametxlcn.logger.jdbcurl={spring.datasource.url}
tx-lcn.logger.username= s p r i n g . d a t a s o u r c e . u s e r n a m e t x − l c n . l o g g e r . p a s s w o r d = {spring.datasource.username} tx-lcn.logger.password= spring.datasource.usernametxlcn.logger.password={spring.datasource.password}

给出信息都是默认值

关于详细配置说明见TM配置
application.properties 加载顺序如下:
0、命令行启动参数指定
1、file:./config/(当前jar目录下的config目录)
2、file:./(当前jar目录)
3、classpath:/config/(classpath下的config目录)
4、classpath:/(classpath根目录)
发布的二进制可执行Jar包含一个默认配置文件(也就是4),可按需要覆盖默认配置
把txlcn-tm的pom打包方式修改成
Copy



org.springframework.boot
spring-boot-maven-plugin



手动编译TM,简单指引
Copy

git clone https://github.com/codingapi/tx-lcn.git & cd txlcn-tm

mvn clean package ‘-Dmaven.test.skip=true’

target文件夹下,即为Ttxlcn-tm-5.0.2.RELEASE.jar

TC微服务模块#
arch

服务A作为DTX发起方,远程调用服务B
工程说明#
finchley 父项目主要进行依赖管理
common-config 可存方公共配置级工具
common-eureka 服务注册中心
gateway-zuul 网关
user-server 服务1
money-server 服务2
忽略其他工程搭建步骤。

事务操作实例#
user-server 提供远程服务,money-server通过fegin发现服务调用进行事务回滚。

这两个服务需要加入依赖,如下:

Copy

com.codingapi.txlcn txlcn-tc 5.0.2.RELEASE com.google.guava guava com.codingapi.txlcn txlcn-txmsg-netty 5.0.2.RELEASE com.google.guava guava 依赖最好跟随TM管理器版本,方式出现奇怪问题。

两个工程的启动类使用该@EnableDistributedTransaction标记启动分布式事务。

两个工程properties需要加入事务管理器监控地址,如下:

Copy
#该配置根据TM打包时的配置进行
tx-lcn.client.manager-address=127.0.0.1:8070
在user-server 和money-server插入数据,server实例:

Copy
/**

  • user-server
  • @Auhotr:SimpleWu
  • @TxTransaction 使用该注解启动分布式事务
  • @Transactional 同时使用spring事务开启本地事务
  • 插入一个用户
    */
    @Override
    @TxTransaction
    @Transactional
    public int insertUser(Map map) {
    userServerMapper.insert(map);
    return “insertUser success”;
    }
    Copy
    //fegin调用user-server服务
    @Autowired
    private UserFegin userFegin;

//对money表操作mapper
@Autowired
private MoneyServerMapper moneyServerMapper;

/**

  • user-server

  • @Auhotr:SimpleWu

  • @TxTransaction 使用该注解启动分布式事务

  • @Transactional 同时使用spring事务开启本地事务

  • 插入一个用户
    */
    @Override
    @TxTransaction
    @Transactional
    public String insert() {
    String userId = UUID.randomUUID().toString();

     Map param = new HashMap<>();
     param.put("ID",userId);
     param.put("USER_ID",userId);
     param.put("MONEY",100);
     param.put("USERPASS","12321321");
    
     //先调用远程服务测试事务回滚
     System.out.println( userFegin.hello("张三","12321321",userId));
    
     int i = 0 / 0;
    
     moneyServerMapper.insert(param);
    
     return "success " + param;
    

}
启动顺序:

部署Redis
部署TM的Jar包
部署Eureka服务注册中心
部署user-server服务
部署money-server服务
忽略网关等…
访问money-server服务 :http://localhost:13000/hello 调用 insert();

Copy
int i = 0 / 0;
该行代码发生异常,UserFegin为user-server远程放服务调用后打印"insertUser success"代表调用成功,如果分布式事务没有效果,那么遇见该异常远程方不会进行回滚。

在本次测试是回滚成功的,就不贴图了,亲自尝试才能体会到,那种感觉。

然后删除money-server中删除int i = 0 / 0;重新启动。

再次调用http://localhost:13000/hello调用 insert(),成功插入两条数据。

访问:http://localhost:7970进入TxManager系统后台,登录密码是我们设置的123456。里面可以看到配置信息,以及异常信息日志,系统日志。

该篇案例源代码与工具见:https://github.com/450255266/open-doubi
深圳网站建设https://www.sz886.com

你可能感兴趣的:(技术)