使用tx-lcn完成分布式事务管理

  TxManager是LCN分布式事务框架的事务协调器,框架基于Netty做消息通讯,事务控制数据存储在redis中。

TxManager采用高可用集群化部署方案,多个TM通过eureka集群完成服务注册,各个TxClient通过服务名称向TxManager发送事务信息。

一、搭建TxManager

1、创建一个springboot项目

继承父项目

<parent>
        <groupId>com.zl.stock</groupId>
        <artifactId>stock-parent</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../stock-parent/pom.xml</relativePath>
</parent>

导入相关依赖

<!--添加Eureka-client的依赖 -->
 <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- tx-lcn的事务协调器依赖 -->
<dependency>
      <groupId>com.codingapi.txlcn</groupId>
      <artifactId>txlcn-tm</artifactId>
       <version>5.0.2.RELEASE</version>
</dependency>
<!--目前只支持mysql记录日志--><dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2、在启动类上添加注解,@EnableTransactionManagerServer

@SpringBootApplication
@EnableTransactionManagerServer
@EnableEurekaClient
public class StockTxmanagerApplication {。。}

4、保留默认配置文件application.properties(无内容)

新建一个application.yml文件进行配置

3、配置yml配置文件

#配置端口
server:
port: 8521
#redis相关配置
spring:
  profiles:
    active: dev
  redis:
    host: 127.0.0.1
    port: 6381
  application:
    name: stock-txManager
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver 
    url: jdbc:mysql://localhost:3306/tx-manager?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  jpa:
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect  # 数据库方言
    hibernate.ddl-auto: update  #第一次运行可以设置为: create, 为TM创建持久化数据库表

#eureka相关配置
eureka:
  instance:
    hostname: 127.0.0.1
    #修改eureka-client在注册中心页面显示的名字
    #${spring.cloud.client.ipaddress} 获取服务的ip地址
    instance-id: stock-txManager-${spring.cloud.client.ipaddress}-${server.port}
    #服务信息显示的真实的ip, 开发中一定要设置为true, 如果不设置, 其他电脑访问不到你的服务
    prefer-ip-address: true
  client:
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:10001/eureka/

tx-lcn:
  manager:
    host: 127.0.0.1 # tx-manager ip(client请求ip)
    port: 8070  # client 请求端口
    heart-time: 12000 # 心跳检测时间 单位:ms
    dtx-time: 3000 # 事务执行总时间
    admin-key: 123456 #TM后台登陆密码,默认密码是codingapi
  logger:
    enabled: true #开启日志,默认为false,开发阶段最好开启日志,并设置为debug等级,这样方便追踪排查问题
    #日志记录表 t_logger
    driver-class-name: ${spring.datasource.driver-class-name}
    jdbc-url: ${spring.datasource.url}
    username: ${spring.datasource.username}
    password: ${spring.datasource.password}
logging:
  level:
    com:
      codingapi:
        txlcn: DEBUG  #日志输出级别

创建成启动Eureka , 在启动TxManager服务  (默认端口为7970)

 启动成功访问:http://127.0.0.1:7970/   (默认密码为codingapi,修改的密码为123456

 二、创建mysql数据库、表来保存日志

1、创建MySQL数据库, 名称为:tx-manager

2、创建数据表:创建异常记录表, 根据tx-lcn的TxException类来创建,表名为: t_tx_exception

创表语句

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 NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;

 三、搭建tx-client,就是需要用到的服务(1、调用者、2、被调用者)

1、在业务服务项目添加相关依赖

<!-- tx-lcn的client相关依赖 -->
<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>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

2、启动类添加 @EnableDistributedTransaction。

//本地事务
@EnableTransactionManagement
//分布式事务
@EnableDistributedTransaction

3、添加yml配置文件

tx-lcn:
  ribbon:
    loadbalancer:
      dtx:
        enabled: true
  # 默认之配置为TM的本机默认端口
  client:
    manager-address: 127.0.0.1:8070
  # 开启日志,默认为false
  logger:
    enabled: true
    driver-class-name: com.mysql.cj.jdbc.Driver 
    jdbc-url: jdbc:mysql://localhost:3306/tx-manager?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

4、在用到事务的service中添加注解(需要添加两个服务我们命名为A、B关系(A调用B))

A中需要事务的地方添加
@LcnTransaction(分布式事务)
@Transactional(本地事务)
在B中需要事务的地方添加
@LcnTransaction
@Transactional

测试

A服务调用B服务

1、在A服务的ServletImpl中:

//给审核开户信息手动分配一个账号(账号使用时间戳获取)TODO 加上分布式事务
    @Override
    @LcnTransaction//分布式事务
    @Transactional//本地事务
    public boolean byCard(T_realuser realuser) throws Exception {
        //随机生成一个十位的账号
        String id = String.valueOf(Long.parseLong(String.valueOf(System.currentTimeMillis())
                    .substring(1,10).concat(String.valueOf(0))));
       // String timer = new Date().getTime()+"";
        realuser.setAccountid(id);
        realuser.setUpdatetime(new Date());

        //修改user表中的激活状态 ** (B服务中的方法)
        userClientService.updateUserStatus(realuser.getRusid());
        return getBaseMapper().updateById(realuser) >0 ?true :false;
    }

2、在B服务被调用的ServletImpl中:

//审核通过将状态列改为1
    @Override
    @LcnTransaction//分布式事务
    @Transactional//本地事务
    public boolean updateUserStatus(T_user user) throws Exception {
        //修改时间
        user.setUpdatetime(new Date());
        //修改状态
        user.setStatus(1);
        //自定义异常,测试分布式事务是否成功 -- 查看是否回滚
        int a = 10/0;
        return getBaseMapper().updateById(user) >0 ?true :false;
    }

3、执行方法

 报错,查看数据库是否更改数据

数据库中:两张表的数据库都没有进行更改

4、查看mysql错误日志

 5、也可以在TxManager系统后台中查看错误日志

 

posted @ 2020-08-03 16:03  64Byte  阅读(828)  评论(0编辑  收藏  举报