您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
spring boot 分布式事务解决方案LCN
 
   次浏览      
 2019-9-25
 
编辑推荐:

本文来自于 csdn,将从原理,调用时序图,客户端,启动类配置代理连接池,测试代码和效果这几个方面来阐述分布式事务解决方案LCN。

对比LCN和saga(华为apache孵化器项目) ,LCN使用代理连接池封 装补偿方法,saga需要手工写补偿方法,相对来说LCN使用更加方便。

参考官方地址

1. 原理

1. 事务控制原理

LCN事务控制原理是由事务模块TxClient下的代理连接池与TxManager 的协调配合完成的事务协调控制。

TxClient的代理连接池实现了javax.sql.DataSource接口, 并重写了close方法,事务模块在提交关闭以后TxClient连接池将执行"假关闭"操作,等待TxManager协调完成事务以后在关闭连接。

2. 调用时序图

1. 正常

2. 异常

2. 服务端

tx-manager 4.1.0

3. 客户端

1. pom添加依赖

<properties>
<lcn.last.version>4.1.0</lcn.last.version>
</properties>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<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>

2. 配置文件

#Ribbon的负载均衡策略:随机
#ribbon.NFLoadBalancerRuleClassName= com.netflix.loadbalancer.RandomRule
#由于springcloud默认是开启的重试机制,开启次机制以后会导致当springcloud请求超时时会重复调用业务模块, 从而会引发数据混乱,因此建议将其禁用。对于网络模块超时等故障问题建议使用hytrix方式。
#ribbon.MaxAutoRetriesNextServer=0

tm:
manager:
url: http://localhost:8899/tx/manager/
ribbon:
NFLoadBalancerRuleClassName: com.netflix. loadbalancer.RandomRule
MaxAutoRetriesNextServer: 0
init-db:true
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000

3. Service包下处理http请求和对服务器的连接

package com.svw.tbox.tcloud.commons.ms.service;

import com.codingapi.tx.netty.service. TxManagerHttpRequestService;
import com.lorne.core.framework.utils.http.HttpUtils;
import org.springframework.stereotype.Service;

@Service
publicclass TxManagerHttpRequestServiceImpl implements TxManagerHttpRequestService{

@Override
public String httpGet(String url) {
//GET请求前
String res = HttpUtils.get(url);
//GET请求后
returnres;
}

@Override
public String httpPost(String url, String params) {
//POST请求前
String res = HttpUtils.post(url,params);
//POST请求后
returnres;
}
}
package com.svw.tbox.tcloud.commons.ms.service;

import com.codingapi.tx.config.service. TxManagerTxUrlService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class TxManagerTxUrlServiceImpl implements TxManagerTxUrlService{

@Value("${tm.manager.url}")
private String url;

@Override
public String getTxUrl() {
//load tm.manager.url
return url;
}
}

4. 启动类配置代理连接池

import javax.sql.DataSource;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot. autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery. EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.context. annotation.ComponentScan;
import org.springframework.core.env.Environment;
import com.alibaba.druid.pool.DruidDataSource;

@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@MapperScan(basePackages = "com.svw.tbox.tcloud. commons.ms.dao")
@ComponentScan(basePackages = { "com.svw.tbox.tcloud" })
publicclass MsApplication {
……
@Autowired
private Environment env;

@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty ("spring.datasource.username"));//用户名
dataSource.setPassword(env.getProperty ("spring.datasource.password"));//密码
dataSource.setInitialSize(2);
dataSource.setMaxActive(20);
dataSource.setMinIdle(0);
dataSource.setMaxWait(60000);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestOnBorrow(false);
dataSource.setTestWhileIdle(true);
dataSource.setPoolPreparedStatements(false);
returndataSource;
}

5. 测试代码

调用方tcloud-mds => 参与方tcloud-commons

package com.svw.tbox.tcloud.commons.api.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import com.svw.tbox.tcloud.commons.api.config. TxFeignConfiguration;
import com.svw.tbox.tcloud.commons.api.service. SysErrorCodeMappingService;

/**
* <p>ClassName: SysErrorCodeMappingFeign</p>
* <p>Description: 远程调用错误码服务</p>
* <p>Author: hurf</p>
* <p>Date: 2017年12月11日</p>
*/
@FeignClient(value = "tcloud-commons-ms")
publicinterface SysErrorCodeMappingFeign extends SysErrorCodeMappingService {
}

2. 事务发起@TxTransaction(isStart=true)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.codingapi.tx.annotation.TxTransaction;
import com.svw.tbox.tcloud.commons.api. entity. SysErrorCodeMapping;
import com.svw.tbox.tcloud.commons.api. feign.SysErrorCodeMappingFeign;
import com.svw.tbox.tcloud.commons.api.service.CmnService;
import com.svw.tbox.tcloud.commons.api.service.JedisTemplate;
import com.svw.tbox.tcloud.commons.util.DateUtil;
import com.svw.tbox.tcloud.mds.entity.ThUserLogin;

/**
* @Title<p>ClassName: UserTokenService</p>
* @Description<p>Description: 登录服务</p>
* @Author<p>Author: hurf</p>
* @Date<p>Date: 2018年2月6日</p>
*/
@Service
publicclass UserTokenService extends CmnService<ThUserLogin>{
@Autowired
private JedisTemplate jedisTemplate;

@Autowired
private SysErrorCodeMappingFeign sysErrorCodeMappingFeign;

@Transactional
@TxTransaction(isStart=true)
public String add(SysErrorCodeMapping sysErrorCodeMapping) {
// 远程调用新增
sysErrorCodeMappingFeign.add(sysErrorCodeMapping);
// 本地新增db
insertSelective(ThUserLogin.builder().accessToken (sysErrorCodeMapping.getApiCode())
.refreshToken(sysErrorCodeMapping.getInnerErrorCode()). createBy ("测试事务").build());
//本地缓存事务
jedisTemplate.set("isStart", DateUtil.getNow());
// int ii = 1/0;//异常

return"测试分布式事务成功";
}
}

3. 事务参与方tcloud-commons-ms: @Transactional

@RestController
publicclass SysErrorCodeMappingController implements SysErrorCodeMappingService {

@Autowired
private MsService msService;

@ApiOperation("添加错误码信息")
@Override
public SystemResponse add (@RequestBody SysErrorCodeMapping sysErrorCodeMapping) {
returnmsService.add(sysErrorCodeMapping);
}
。。。。。。
importcom.codingapi.tx.annotation.ITxTransaction;

@Service
@CacheConfig(cacheNames = "sys-code-resource")
publicclass MsService implements ITxTransaction{

@Autowired
private JedisTemplate jedisTemplate;

@Autowired
private SysErrorCodeMappingMapper sysErrorCodeMappingMapper;
/**
* <p>Title: 事务参与方</p>
* <p>Description: </p>
* @param sysErrorCodeMapping
* @return
*/
@Transactional
public SystemResponse add( SysErrorCodeMapping sysErrorCodeMapping) {
//db操作
sysErrorCodeMapping.setVersion(1);
sysErrorCodeMapping.setDelFlag(Short.valueOf("0"));
sysErrorCodeMapping.setCreatedBy("admin");
sysErrorCodeMapping.setCreateDate(new Date());
sysErrorCodeMappingMapper.insertSelective (sysErrorCodeMapping);

//redis操作
jedisTemplate.set ("addTest"+DateUtil.getNow(),"ttttttttttt ttttttttttt");
return ResultUtil.success(refreshAll());
}

6. 效果

启动两个微服务,访问调用方接口

1. 正常情况

2. 异常回滚情况

删除刚刚的测试数据,开启异常情况:

@Transactional
@TxTransaction(isStart=true)
public String add(SysErrorCodeMapping sysErrorCodeMapping) {
// 远程调用新增
sysErrorCodeMappingFeign.add(sysErrorCodeMapping);
// 本地新增db
insertSelective( ThUserLogin.builder().accessToken( sysErrorCodeMapping.getApiCode())
.refreshToken( sysErrorCodeMapping.getInnerErrorCode()).createBy( "测试事务").build());
//本地缓存事务
jedisTemplate.set( "isStart", DateUtil.getNow());
intii = 1/0;//异常

return"测试分布式事务成功";
}

发现mysql已经回滚了,但是redis没有回滚 =》 目前只支持db分布式事务。

   
次浏览       
相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践