springcloud使用LCN分布式事务

本文围绕LCN分布式事务展开,介绍了tx - manager的配置,包括注册到Eureka、依赖问题、启动报错处理等。还给出了maven依赖配置,阐述了tx - manager需配置redis和注册中心。同时说明了微服务中引入LCN事务的方法,如配置地址、添加注解等,以及分布式事务回滚情况。

此文为装载,前面根据自己参考的资料搭建时遇到问题先说明一下

1,tx-manager是个什么东西? 它是独立的服务,要想实现分布式事务,要把它注册到Eureka,与其他服务一样配置

2,到底下载哪个tx-manager,大部分文章给了下面这个地址,是图2这个东西吗?我下载的并不是这个

3,gradle依赖问题:我用的是gradle,开始依赖的jar,没有排除日志依赖,导致日志冲突,无法启动,gradle依赖如图3

4,启动报错,找不到tx.properties文件问题,应该把下文中TxManagerTxUrlServiceImpl类,定义为配置类如图4

5,配置Erueka,我下载的tx-manager如图5,没有bootstrap.yml文件,为了统一cloud配置,我把properties中配置放到这个配置文件中,其实除了自身的端口和服务名外,其他跟其他微服务一样

6,先启动tx-manager,必须先启动该服务,不然先启动其他服务会报错;切换到tx-manager所在文件,通过命令启动,如图6

7,跨服务调用失败,我在测试时,想跨服务调用另外一个服务修改接口,结果无法调通,报错内容是-无法连接主机;然后我把tx-manager相关依赖去掉可以调通,说明原因在这里,未解决

图2

 图3

    compile('com.codingapi:transaction-springcloud:4.1.0'){
        exclude group: 'org.slf4j', module: '*'
    }
    compile('com.codingapi:tx-plugins-db:4.1.0'){
        exclude group: 'org.slf4j', module: '*'
    }

图4

 图5

图6 

-------------------------------------------------------------------------------------------------------------------------------------

本人使用LCN4.1.0版本(数据库是mysql,注册中心eureka)

LCN分布式事务官网:http://www.txlcn.org/

springcloud的demo:https://github.com/codingapi/springcloud-lcn-demo

tx-manager事务控制器服务端:https://github.com/codingapi/tx-lcn

1、maven依赖

        <!-- LCN分布式事务相关依赖 -->
        <dependency>
            <groupId>com.codingapi</groupId>
            <artifactId>transaction-springcloud</artifactId>
            <version>${lcn.last.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.codingapi</groupId>
            <artifactId>tx-plugins-db</artifactId>
            <version>${lcn.last.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    <properties>
        <!-- LCN分布式事务版本 -->
        <lcn.last.version>4.1.0</lcn.last.version>
    </properties>
2、tx-manager

作者提供的tx-manager是LCN分布式事务的事务中间件,需要springcloud微服务框架需要与tx-manager进行通信,通过tx-manager协调微服务之间的事务调用。

tx-manager需要配置redis和注册中心(源码默认配置eureka,参考作者官网也可以配置zookeeper)

配置在源码的application.property文件

#######################################txmanager-start#################################################
#服务端口
server.port=8899
 
#tx-manager不得修改
spring.application.name=tx-manager
 
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/static/
#######################################txmanager-end#################################################
 
 
#zookeeper地址
#spring.cloud.zookeeper.connect-string=127.0.0.1:2181
#spring.cloud.zookeeper.discovery.preferIpAddress = true
 
#eureka 地址
eureka.client.service-url.defaultZone=http://127.0.0.1:8761/eureka/
eureka.instance.prefer-ip-address=true
 
#######################################redis-start#################################################
#redis 配置文件,根据情况选择集群或者单机模式
 
##redis 集群环境配置
##redis cluster
#spring.redis.cluster.nodes=127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
#spring.redis.cluster.commandTimeout=5000
 
##redis 单点环境配置
#redis
#redis主机地址
spring.redis.host=127.0.0.1
#redis主机端口
spring.redis.port=6379
#redis链接密码
spring.redis.password=
spring.redis.pool.maxActive=10
spring.redis.pool.maxWait=-1
spring.redis.pool.maxIdle=5
spring.redis.pool.minIdle=0
spring.redis.timeout=0
#####################################redis-end###################################################
 
 
 
 
#######################################LCN-start#################################################
#业务模块与TxManager之间通讯的最大等待时间(单位:秒)
#通讯时间是指:发起方与响应方之间完成一次的通讯时间。
#该字段代表的是Tx-Client模块与TxManager模块之间的最大通讯时间,超过该时间未响应本次请求失败。
tm.transaction.netty.delaytime = 5
 
#业务模块与TxManager之间通讯的心跳时间(单位:秒)
tm.transaction.netty.hearttime = 15
 
#存储到redis下的数据最大保存时间(单位:秒)
#该字段仅代表的事务模块数据的最大保存时间,补偿数据会永久保存。
tm.redis.savemaxtime=30
 
#socket server Socket对外服务端口
#TxManager的LCN协议的端口
tm.socket.port=9999
 
#最大socket连接数
#TxManager最大允许的建立连接数量
tm.socket.maxconnection=100
 
#事务自动补偿 (true:开启,false:关闭)
# 说明:
# 开启自动补偿以后,必须要配置 tm.compensate.notifyUrl 地址,仅当tm.compensate.notifyUrl 在请求补偿确认时返回success或者SUCCESS时,才会执行自动补偿,否则不会自动补偿。
# 关闭自动补偿,当出现数据时也会 tm.compensate.notifyUrl 地址。
# 当tm.compensate.notifyUrl 无效时,不影响TxManager运行,仅会影响自动补偿。
tm.compensate.auto=false
 
#事务补偿记录回调地址(rest api 地址,post json格式)
#请求补偿是在开启自动补偿时才会请求的地址。请求分为两种:1.补偿决策,2.补偿结果通知,可通过通过action参数区分compensate为补偿请求、notify为补偿通知。
#*注意当请求补偿决策时,需要补偿服务返回"SUCCESS"字符串以后才可以执行自动补偿。
#请求补偿结果通知则只需要接受通知即可。
#请求补偿的样例数据格式:
#{"groupId":"TtQxTwJP","action":"compensate","json":"{\"address\":\"133.133.5.100:8081\",\"className\":\"com.example.demo.service.impl.DemoServiceImpl\",\"currentTime\":1511356150413,\"data\":\"C5IBLWNvbS5leGFtcGxlLmRlbW8uc2VydmljZS5pbXBsLkRlbW9TZXJ2aWNlSW1wbAwSBHNhdmUbehBqYXZhLmxhbmcuT2JqZWN0GAAQARwjeg9qYXZhLmxhbmcuQ2xhc3MYABABJCo/cHVibGljIGludCBjb20uZXhhbXBsZS5kZW1vLnNlcnZpY2UuaW1wbC5EZW1vU2VydmljZUltcGwuc2F2ZSgp\",\"groupId\":\"TtQxTwJP\",\"methodStr\":\"public int com.example.demo.service.impl.DemoServiceImpl.save()\",\"model\":\"demo1\",\"state\":0,\"time\":36,\"txGroup\":{\"groupId\":\"TtQxTwJP\",\"hasOver\":1,\"isCompensate\":0,\"list\":[{\"address\":\"133.133.5.100:8899\",\"isCompensate\":0,\"isGroup\":0,\"kid\":\"wnlEJoSl\",\"methodStr\":\"public int com.example.demo.service.impl.DemoServiceImpl.save()\",\"model\":\"demo2\",\"modelIpAddress\":\"133.133.5.100:8082\",\"channelAddress\":\"/133.133.5.100:64153\",\"notify\":1,\"uniqueKey\":\"bc13881a5d2ab2ace89ae5d34d608447\"}],\"nowTime\":0,\"startTime\":1511356150379,\"state\":1},\"uniqueKey\":\"be6eea31e382f1f0878d07cef319e4d7\"}"}
#请求补偿的返回数据样例数据格式:
#SUCCESS
#请求补偿结果通知的样例数据格式:
#{"resState":true,"groupId":"TtQxTwJP","action":"notify"}
tm.compensate.notifyUrl=http://ip:port/path
 
#补偿失败,再次尝试间隔(秒),最大尝试次数3次,当超过3次即为补偿失败,失败的数据依旧还会存在TxManager下。
tm.compensate.tryTime=30
 
#各事务模块自动补偿的时间上限(毫秒)
#指的是模块执行自动超时的最大时间,该最大时间若过段会导致事务机制异常,该时间必须要模块之间通讯的最大超过时间。
#例如,若模块A与模块B,请求超时的最大时间是5秒,则建议改时间至少大于5秒。
tm.compensate.maxWaitTime=5000
#######################################LCN-end#################################################
 
 
 
 
logging.level.com.codingapi=debug

3、微服务中引入LCN事务

(1)配置tx-manager的url地址,每个微服务都需要配置

方式一: 使用默认方式是添加tx.properties文件,内容如下

#txmanager地址

url=http://127.0.0.1:8899/tx/manager/

方式二: 自定义url的配置.

编写配置文件到application.properties文件下

key:tm.manager.url

如tm.manager.url=http://127.0.0.1:8899/tx/manager/。

重写读取配置文件的类TxManagerTxUrlService。

import com.codingapi.tx.config.service.TxManagerTxUrlService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
 
/**
 * create by lorne on 2017/11/18
 */
@Service
public class TxManagerTxUrlServiceImpl implements TxManagerTxUrlService{
 
 
    @Value("${tm.manager.url}")
    private String url;
 
    @Override
    public String getTxUrl() {
        System.out.println("load tm.manager.url ");
        return url;
    }
}
配置文件

#txmanager地址
tm.manager.url=http://127.0.0.1:8899/tx/manager/
(2)如何将tx-manager的访问地址设置为服务发现的方式.
重写写TxManagerHttpRequestService自定义方法方式.
demo里面是调用方微服务才添加这个

import com.codingapi.tx.netty.service.TxManagerHttpRequestService;
import com.lorne.core.framework.utils.http.HttpUtils;
import org.springframework.stereotype.Service;
 
/**
 * create by lorne on 2017/11/18
 */
 
@Service
public class TxManagerHttpRequestServiceImpl implements TxManagerHttpRequestService{
 
    @Override
    public String httpGet(String url) {
        System.out.println("httpGet-start");
        String res = HttpUtils.get(url);
        System.out.println("httpGet-end");
        return res;
    }
 
    @Override
    public String httpPost(String url, String params) {
        System.out.println("httpPost-start");
        String res = HttpUtils.post(url,params);
        System.out.println("httpPost-end");
        return res;
    }
}
(3)调用方添加注解@TxTransaction(isStart = true)

注:同时也要添加普通的spring事务注解

    @Override
    @TxTransaction(isStart = true)
    @Transactional
    public int save() throws Exception {
 
        //本地微服务
        int rs1 = testMapper.save("mybatis-hello-1");
        //被调用方微服务
        int rs2 = demo2Client.save();
 
//        int rs22 = demo2Client.save();
 
        int v = 100/0;
        
        return rs1+rs2;
    }
(4)被调用方微服务里面需要分布式事务调用的类要继承接口ITxTransaction

import com.codingapi.tx.annotation.ITxTransaction;
import com.example.demo.dao.TestMapper;
import com.example.demo.entity.Test;
import com.example.demo.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.util.List;
 
/**
 * Created by lorne on 2017/6/26.
 */
@Service
public class DemoServiceImpl implements DemoService ,ITxTransaction{
 
    @Autowired
    private TestMapper testMapper;
 
 
 
    @Override
    public List<Test> list() {
        return testMapper.findAll();
    }
 
    //被调用的方法,添加普通的spring事务注解
    @Override
    @Transactional
    public int save() {
 
        int rs = testMapper.save("mybatis-hello-2");
 
        return rs;
    }
}
(5)只要整个分布式调用过程中抛RuntimeException异常,则分布式事务能正常触发回滚,亲测可行
 

编辑推荐: 本文来自于csdn,本篇文章主要介绍了LCN5.0.2有3种模式,分别是LCN模式,TCC模式,TXC模式,希望对您的学习 有所帮助。 一、简介 LCN分布式事务框架其本身并不创建事务,而是基于对本地事务的协调从而达到事务一致性的效果。 LCN模式: LCN模式是通过代理Connection的方式实现对本地事务的操作,然后在由TxManager统一协调控制事务。当本地事务提交回滚或者关闭连接时将会执行假操作,该代理的连接将由LCN连接池管理。 该模式的特点: - 该模式对代码的嵌入性为低。 - 该模式仅限于本地存在连接对象且可通过连接对象控制事务的模块。 - 该模式下的事务提交与回滚是由本地事务方控制,对于数据一致性上有较高的保障。 - 该模式缺陷在于代理的连接需要随事务发起方一共释放连接,增加了连接占用的时间。 TCC模式: TCC事务机制相对于传统事务机制(X/Open XA Two-Phase-Commit),其特征在于它不依赖资源管理器(RM)对XA的支持,而是通过对(由业务系统提供的)业务逻辑的调度来实现分布式事务。主要由三步操作,Try: 尝试执行业务、 Confirm:确认执行业务、 Cancel: 取消执行业务。 该模式的特点: - 该模式对代码的嵌入性高,要求每个业务需要写三种步骤的操作。 - 该模式对有无本地事务控制都可以支持使用面广。 - 数据一致性控制几乎完全由开发者控制,对业务开发难度要求高。 TXC模式: TXC模式命名来源于淘宝,实现原理是在执行SQL之前,先查询SQL的影响数据,然后保存执行的SQL快走信息和创建锁。当需要回滚的时候就采用这些记录数据回滚数据库,目前锁实现依赖redis分布式锁控制。 该模式的特点: - 该模式同样对代码的嵌入性低。 - 该模式仅限于对支持SQL方式的模块支持。 - 该模式由于每次执行SQL之前需要先查询影响数据,因此相比LCN模式消耗资源与时间要多。 - 该模式不会占用数据库的连接资源。 二、原理 核心步骤 1.创建事务组 是指在事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。 2.添加事务组 添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息添加通知给TxManager的操作。 3.关闭事务组 是指在发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager的动作。当执行完关闭事务组的方法以后,TxManager将根据事务组信息来通知相应的参与模块提交或回滚事务。 事务控制原理 LCN事务控制原理是由事务模块TxClient下的代理连接池与TxManager的协调配合完成的事务协调控制。 TxClient的代理连接池实现了javax.sql.DataSource接口,并重写了close方法,事务模块在提交关闭以后TxClient连接池将执行"假关闭"操作,等待TxManager协调完成事务以后在关闭连接。 对于代理连接池的优化 自动超时机制,任何通讯都有最大超时限制,参与模块在等待通知的状态下也有最大超时限制,当超过时间限制以后事务模块将先确认事务状态,然后再决定执行提交或者回滚操作,主要为了给最大资源占用时间加上限制。 智能识别创建不同的连接 对于只读操作、非事务操作LCN将不开启代理功能,返回本地连接对象,对于补偿事务的启动方将开启回滚连接对象,执行完业务以后马上回滚事务。 LCN连接重用机制 当模块在同一次事务下被重复执行时,连接资源会被重用,提高连接的使用率。 事务补偿机制 为什么需要事务补偿? 事务补偿是指在执行某个业务方法时,本应该执行成功的操作却因为服务器挂机或者网络抖动等问题导致事务没有正常提交,此种场景就需要通过补偿来完成事务,从而达到事务的一致性。 补偿机制的触发条件? 当执行关闭事务组步骤时,若发起方接受到失败的状态后将会把该次事务识别为待补偿事务,然后发起方将该次事务数据异步通知给TxManager。TxManager接受到补偿事务以后先通知补偿回调地址,然后再根据是否开启自动补偿事务状态来补偿或保存该次切面事务数据。 补偿事务机制 LCN的补偿事务原理是模拟上次失败事务的请求,然后传递给TxClient模块然后再次执行该次请求事务。 模拟场景演示 若存在事务发起方、参与方A、参与方B。调用关系图如下 那么他们正常执行业务的时序图为: 若参与方B出现异常,那么他们的业务时序图为: 若他们的调用关系是这样的情况 此时发生参与方B出现异常时他们的时序图为: 三、使用 环境: SpringBoot 2.0.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值