分布式事务(TXLcn详细使用,实现分布式事务)

1.TXLcn介绍

TX-LCN 主要有两个模块,Tx-Client(TC) Tx-Manager™. TC作为微服务下的依赖,TM是独立的服务,主要作为事务管理的控制中心。
在这里插入图片描述
发起方发起会缓存事务的gtoupid到tx-manager中,根据最后的处理结果进行commit或者cancel操作。根据官网,tx-manager是支持集群服务的。

2.TXLcn使用

2.1 准备数据库

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.2 父pom

此处需要注意,如果夫pom中版本控制器细度化过高,注意是否与LCN官方版本是否一致(此处建议一致)


    <properties>
        <!-- project -setting -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>

        <codingapi.txlcn.version>5.0.2.RELEASE</codingapi.txlcn.version>
        <springcloud.version>Greenwich.RELEASE</springcloud.version>
        <lombok.version>1.18.0</lombok.version>
        <druid.version>1.1.12</druid.version>
        <mybatis.spring.version>2.1.1</mybatis.spring.version>

    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
        <relativePath/>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <!-- spring cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${springcloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>1.2.5</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>
            <!-- tx lcn 分布式事务 -->
            <dependency>
                <groupId>com.codingapi.txlcn</groupId>
                <artifactId>txlcn-tc</artifactId>
                <version>${codingapi.txlcn.version}</version>
            </dependency>
            <dependency>
                <groupId>com.codingapi.txlcn</groupId>
                <artifactId>txlcn-tm</artifactId>
                <version>${codingapi.txlcn.version}</version>
            </dependency>
            <dependency>
                <groupId>com.codingapi.txlcn</groupId>
                <artifactId>txlcn-txmsg-netty</artifactId>
                <version>${codingapi.txlcn.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

2.3 建立官方tx-lcn的demo

此处可以有两种方式,①下载官方jar包修改application.properties,使用java-jar实现 ②配置至自己项目中

2.3.1 启动类
package com.kim.tx.lcn;

import com.codingapi.txlcn.tm.config.EnableTransactionManagerServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableTransactionManagerServer
public class TransactionManagerApplication {

    public static void main(String[] args) {
        SpringApplication.run(TransactionManagerApplication.class, args);
    }
}

2.3.2 配置文件

如果redis本地存在不一致,需设置redis

##################
# 这个是启动本服务的配置文件,其它的application-xxx.properties 是开发者的个性化配置,不用关心。
# 你可以在 https://txlcn.org/zh-cn/docs/setting/manager.html 看到所有的个性化配置
#################

spring.application.name=TransactionManager
server.port=7970
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://xxxxxxxx:3306/members?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=xxxxxxxx
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

2.3.3 pom文件

    <dependencies>

        <dependency>
            <groupId>com.codingapi.txlcn</groupId>
            <artifactId>txlcn-tm</artifactId>
        </dependency>

    </dependencies>

项目的目录结构如下图:
在这里插入图片描述
启动服务
在这里插入图片描述

访问 http://127.0.0.1:7970/admin/index.html进入管理后台,默认密码是:codingapi
在这里插入图片描述
集成了TC的服务端启动成功后可以点这里查看服务的状态。
具体的Tx-Manager操作,看官网文档吧。
https://www.txlcn.org/zh-cn/docs/manageradmin.html

3 服务调用方

3.1 pom文件加入

加入这两个依赖
<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>
    <dependencies>
-------------------------------------------------完整如下---------------------------------------- 
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- feign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- 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>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.kim</groupId>
            <artifactId>kim-user-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.kim</groupId>
            <artifactId>kim-common-utils</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.kim</groupId>
            <artifactId>kim-redis-starter</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

3.2 启动类增加注解

启动类增加
@EnableDistributedTransaction
-------------------------------------------------完整如下----------------------------------------

@SpringBootApplication
@EnableFeignClients(basePackages = {"com.kim.openfeign.feign"})
@EnableDiscoveryClient
@EnableEurekaClient
@EnableDistributedTransaction //分布式事务
public class FeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(FeignApplication.class,args);
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }
}

3.3 加入本地事务配置类

@Configuration
@EnableTransactionManagement
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AopTypeDTXConfiguration {

    /**
     * 本地事务配置
     *
     * @param transactionManager
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {
        Properties properties = new Properties();
        properties.setProperty("*", "PROPAGATION_REQUIRED,-Throwable");
        TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
        transactionInterceptor.setTransactionManager(transactionManager);
        transactionInterceptor.setTransactionAttributes(properties);
        return transactionInterceptor;
    }

    /**
     * 分布式事务配置 设置为LCN模式
     *
     * @param dtxLogicWeaver
     * @return
     */
    @ConditionalOnBean(DTXLogicWeaver.class)
    @Bean
    public TxLcnInterceptor txLcnInterceptor(DTXLogicWeaver dtxLogicWeaver) {
        TxLcnInterceptor txLcnInterceptor = new TxLcnInterceptor(dtxLogicWeaver);
        Properties properties = new Properties();
        properties.setProperty(Transactions.DTX_TYPE, Transactions.LCN);
        properties.setProperty(Transactions.DTX_PROPAGATION, "REQUIRED");
        txLcnInterceptor.setTransactionAttributes(properties);
        return txLcnInterceptor;
    }

    @Bean
    public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
        beanNameAutoProxyCreator.setInterceptorNames("txLcnInterceptor", "transactionInterceptor");
        beanNameAutoProxyCreator.setBeanNames("*Impl");
        return beanNameAutoProxyCreator;
    }
}

3.4 feign实现类


@Component
@Slf4j
public class UserFeignImpl implements UserFeign {
    @Override
    public Result<SysUser> findByUsername(String username) {
        log.info("findByUsername Feign调用失败,事务回滚!");
        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
        return Result.error(CodeMsg.TX_LCN_BACK);
    }

    @Override
    public Result<String> userInsert(String userName) {
        log.info("userInsert Feign调用失败,事务回滚!");
        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
        return Result.error(CodeMsg.TX_LCN_BACK);
    }

    @Override
    public Result<String> roleInsert(String roleName) {
        log.info("roleInsert Feign调用失败,事务回滚!");
        DTXUserControls.rollbackGroup(TracingContext.tracing().groupId());
        return Result.error(CodeMsg.TX_LCN_BACK);
    }
}


3.5 配置文件

增加
logging:
  level:
    com:
      codingapi:
        txlcn: DEBUG
tx-lcn:
  ribbon:
    loadbalancer:
      dtx:
        enabled: true # 是否启动LCN负载均衡策略(优化选项,开启与否,功能不受影响)
  client:
    manager-address: 127.0.0.1:8070 #指定TM地址
  logger:
    enabled: true # 开启日志,默认为false
    driver-class-name: ${spring.datasource.driver-class-name}
    jdbc-url: ${spring.datasource.url}
    username: ${spring.datasource.username}
    password: ${spring.datasource.password}

#开启Feign的熔断Fallback
feign:
  hystrix:
    enabled: true
#关闭Ribbon重试机制:
ribbon:
  ConnectTimeout: 5000
  ReadTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 0
  -------------------------------------------------完整如下----------------------------------------
  server:
  port: 31001
spring:
  application:
    name: kim-feign
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://xxxxxxxx:3306/members?useSSL=false&autoReconnect=true&characterEncoding=utf-8
    username: root
    password: xxxxxxxx
#  jackson: #时间全局处理
#    date-format: yyyy-MM-dd HH:mm:ss
#    time-zone: GMT+8
  redis: #配置redis
    host: 127.0.0.1
    port: 6379
    timeout: 6000 # 连接超时时间(毫秒)
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1  # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接

eureka:
  client:
    register-with-eureka: true #表示注册到eureka
    fetch-registry: true #是否从eurekaServer抓取已有的注册信息,集群必须设置为true才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://localhost:17001/eureka
  #      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
  instance:
    instance-id: ${spring.application.name}
    prefer-ip-address: true #访问路径可以显示ip
  server: #关闭自我保护机制,保证不可用服务被及时剔除
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000

## consul排错
management:
  endpoint:
    health:
      show-details: always

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 300000
      fallback:
        isolation:
          semaphore:
            maxConcurrentRequests: 50 #设置ribbon的超时时间小于zuul的超时时间


logging:
  level:
    com:
      codingapi:
        txlcn: DEBUG
tx-lcn:
  ribbon:
    loadbalancer:
      dtx:
        enabled: true # 是否启动LCN负载均衡策略(优化选项,开启与否,功能不受影响)
  client:
    manager-address: 127.0.0.1:8070 #指定TM地址
  logger:
    enabled: true # 开启日志,默认为false
    driver-class-name: ${spring.datasource.driver-class-name}
    jdbc-url: ${spring.datasource.url}
    username: ${spring.datasource.username}
    password: ${spring.datasource.password}

#开启Feign的熔断Fallback
feign:
  hystrix:
    enabled: true
#关闭Ribbon重试机制:
ribbon:
  ConnectTimeout: 5000
  ReadTimeout: 60000
  MaxAutoRetries: 0
  MaxAutoRetriesNextServer: 0

3.6 方法调用方法上

新增@LcnTransaction注解

4 服务参与方

4.1 新增依赖

参考3.1

4.2 启动类注解

参考3.2

4.3 配置文件

参考3.5

4.4 调用方法上

新增@LcnTransaction,@Transactional注解
-------------------------------------------------完整如下---------------------------------------
@Override
    @LcnTransaction
    @Transactional
    public int insertRole(SysRole sysRole) {
        log.info("开始执行role insert方法");
        int i = roleMapper.insertSelective(sysRole);
        i = 1 / 0;
        log.info("执行成功");
        return i;
    }

至此,TXLcn搭建完毕,新增抛出异常时,方法内数据库操作都会回滚。TX-LCN就整合完成了!

项目git地址:
https://gitee.com/kim_wu94/kim-distributed-transaction.git

关注公众号
在这里插入图片描述
每周会更新干货知识

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值