dubbo分布式事务解决方案_spring boot 分布式事务解决方案

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家

下一篇:这200G的Java实战资料是我师傅当年教我的第二招

作者:怦然丶心动

来源:www.cnblogs.com/dousnl/p/9772632.html

参考官方地址:

https://github.com/codingapi/tx-lcn/wiki/TxManager%E5%90%AF%E5%8A%A8%E8%AF%B4%E6%98%8E

一.  原理

1.     事务控制原理

7b38a6ee0ed993719b54b6a737614473.png

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

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

2.     调用时序图

正常

d3e11ea2a338e73b47c593a32b533e64.png

异常

aa2c8f6eeae786e4a9a1ea6ed1a98d62.png

二.  服务端

tx-manager 4.1.0

三.  客户端

1.     pom添加依赖

<properties>

        <lcn.last.version>4.1.0lcn.last.version>

    properties>

        <dependency>

            <groupId>org.mybatis.spring.bootgroupId>

            <artifactId>mybatis-spring-boot-starterartifactId>

            <version>1.1.1version>

        dependency>

        <dependency>

            <groupId>com.codingapigroupId>

            <artifactId>transaction-springcloudartifactId>

            <version>${lcn.last.version}version>

            <exclusions>

                <exclusion>

                   <groupId>org.slf4jgroupId>

                   <artifactId>*artifactId>

                exclusion>

            exclusions>

        dependency>

        <dependency>

            <groupId>com.codingapigroupId>

            <artifactId>tx-plugins-dbartifactId>

            <version>${lcn.last.version}version>

            <exclusions>

                <exclusion>

                   <groupId>org.slf4jgroupId>

                   <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

1.     调用方:tcloud-mds
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;

 

/**
 *

ClassName: SysErrorCodeMappingFeign


 *

Description: 远程调用错误码服务


 *

Author: hurf


 *

Date: 2017年12月11日


 */

@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

ClassName: UserTokenService


 * @Description

Description: 登录服务


 * @Author

Author: hurf


 * @Date

Date: 2018年2月6日


 */

@Service

publicclass UserTokenService extends CmnService{@Autowiredprivate JedisTemplate jedisTemplate;@Autowiredprivate 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;

    /**
     *

Title: 事务参与方


     *

Description:


     * @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(),"tttttttttttttttttttttt");

        return ResultUtil.success(refreshAll());

    }

6.     效果

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

1.     正常情况

f853504917d9a98b41d6e99595586ee8.png

2d6fa38c37bbe20bbe14b073ae7a2b82.png

02eed9ab94458e32927567b02e54b1e5.png

88be95a1a8e61494c1d9a6a4600a805e.png

f63c1b0660e477dcc0899b90226586af.png

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"测试分布式事务成功";

    }

 3cd085b3a2dc1c44ffbc0a2950486b9f.png

7dca56a23caee625c94830a711b441dd.png

ed487f3e7c919e4a9fdff9cb42fd7da9.png

0492b3a6f400081ba491b0b4c8f48a8b.png

13344e2715c98c4818a1d16abd85cda2.png

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

说句题外话,springboot全家桶技术交流群可以加我微信,但是坑位有限哦,由于忙于工作,有时不能及时回复大家,请多包涵。

e06c2f819896ceff54b48615f253e11f.png
猜你喜欢

1、去了一趟字节跳动,被怼了!

2、Redis实战--使用Jedis实现百万数据秒级插入

3、Spring Boot+Mybatis+Swagger2 环境搭建

4、TCP/IP,http,socket,长连接,短连接

5、使用Redis之前5个必须了解的事情

6、Spring 体系常用项目一览

7、史上最全的Nginx配置参数中文说明

8、快速搭建ELK日志分析系统

强烈推荐一位大佬的公众号

e22f9df2a444003d68f9b18727619aa3.png

好文章,我在看❤️

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值