关闭

SpringCloud 分布式事务解决方案

发表于:2019-5-27 11:27

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:SimpleWu    来源:博客园

  目录
  TX-LCN分布式事务框架
  随着互联化的蔓延,各种项目都逐渐向分布式服务做转换。如今微服务已经普遍存在,本地事务已经无法满足分布式的要求,由此分布式事务问题诞生。 分布式事务被称为世界性的难题,目前分布式事务存在两大理论依据:CAP定律 BASE理论。
  官网地址:https://www.txlcn.org/zh-cn/
  GitHun:https://github.com/yizhishang/tx-lcn/
  在一个分布式系统下存在多个模块协调来完成一次业务。那么就存在一次业务事务下可能横跨多种数据源节点的可能。TX-LCN将可以解决这样的问题。
  例如存在服务模块A 、B、 C。A模块是mysql作为数据源的服务,B模块是基于redis作为数据源的服务,C模块是基于mongo作为数据源的服务。若需要解决他们的事务一致性就需要针对不同的节点采用不同的方案,并且统一协调完成分布式事务的处理。
 
  方案:
  若采用TX-LCN分布式事务框架,则可以将A模块采用LCN模式、B/C采用TCC模式就能完美解决。
  TX-LCN 主要有两个模块,Tx-Client(TC) Tx-Manager(TM). TC作为微服务下的依赖,TM是独立的服务。
  安装TM需要依赖的中间件: JRE1.8+, Mysql5.6+, Redis3.2+
  如果需要手动编译源码, 还需要Git, Maven, JDK1.8+
  创建MySQL数据库, 名称为: tx-manager
  创建数据表
    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;
  TM下载与配置
  从历史版本TM下载找到5.0.2.RELEASE的TM, 下载.
  修改配置信息
   spring.application.name=tx-manager
  server.port=7970
  spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tx-manager?characterEncoding=UTF-8
  spring.datasource.username=root
  spring.datasource.password=root
  mybatis.configuration.map-underscore-to-camel-case=true
  mybatis.configuration.use-generated-keys=true
  # TxManager Host Ip
  tx-lcn.manager.host=127.0.0.1
  # TxClient连接请求端口
  tx-lcn.manager.port=8070
  # 心跳检测时间(ms)
  tx-lcn.manager.heart-time=15000
  # 分布式事务执行总时间
  tx-lcn.manager.dtx-time=30000
  #参数延迟删除时间单位ms
  tx-lcn.message.netty.attr-delay-time=10000
  tx-lcn.manager.concurrent-level=128
  # TM后台登陆密码,默认值为codingapi
  tx-lcn.manager.admin-key=123456
  logging.level.com.codingapi=debug
  #redis 主机
  spring.redis.host=127.0.0.1
  #redis 端口
  spring.redis.port=6379
  #redis 密码
  spring.redis.password=
  # 开启日志,默认为false
  tx-lcn.logger.enabled=true
  tx-lcn.logger.driver-class-name=${spring.datasource.driver-class-name}
  tx-lcn.logger.jdbc-url=${spring.datasource.url}
  tx-lcn.logger.username=${spring.datasource.username}
  tx-lcn.logger.password=${spring.datasource.password}
  # 给出信息都是默认值
  关于详细配置说明见TM配置
  application.properties 加载顺序如下:
  0、命令行启动参数指定
  1、file:./config/(当前jar目录下的config目录)
  2、file:./(当前jar目录)
  3、classpath:/config/(classpath下的config目录)
  4、classpath:/(classpath根目录)
  发布的二进制可执行Jar包含一个默认配置文件(也就是4),可按需要覆盖默认配置
  把txlcn-tm的pom打包方式修改成
   <build>
  <plugins>
  <plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  </plugin>
  </plugins>
  </build>
   手动编译TM,简单指引
   # git clone https://github.com/codingapi/tx-lcn.git & cd txlcn-tm
  # mvn clean  package '-Dmaven.test.skip=true'
   target文件夹下,即为Ttxlcn-tm-5.0.2.RELEASE.jar
  TC微服务模块
  
  服务A作为DTX发起方,远程调用服务B
  工程说明
  finchley 父项目主要进行依赖管理
  common-config 可存方公共配置级工具
  common-eureka 服务注册中心
  gateway-zuul 网关
  user-server 服务1
  money-server 服务2
  忽略其他工程搭建步骤。
  事务操作实例
  user-server 提供远程服务,money-server通过fegin发现服务调用进行事务回滚。
  这两个服务需要加入依赖,如下:
   <!-- springcloud 分布式事物 -->
  <dependency>
  <groupId>com.codingapi.txlcn</groupId>
  <artifactId>txlcn-tc</artifactId>
  <version>5.0.2.RELEASE</version>
  <exclusions>
  <exclusion>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  </exclusion>
  </exclusions>
  </dependency>
  <dependency>
  <groupId>com.codingapi.txlcn</groupId>
  <artifactId>txlcn-txmsg-netty</artifactId>
  <version>5.0.2.RELEASE</version>
  <exclusions>
  <exclusion>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  </exclusion>
  </exclusions>
  </dependency>
   依赖最好跟随TM管理器版本,方式出现奇怪问题。
  两个工程的启动类使用该@EnableDistributedTransaction标记启动分布式事务。
  两个工程properties需要加入事务管理器监控地址,如下
  #该配置根据TM打包时的配置进行
  tx-lcn.client.manager-address=127.0.0.1:8070
   在user-server 和money-server插入数据,server实例:
   /**
  * user-server
  * @Auhotr:SimpleWu
  * @TxTransaction 使用该注解启动分布式事务
  * @Transactional 同时使用spring事务开启本地事务
  * 插入一个用户
  */
  @Override
  @TxTransaction
  @Transactional
  public int insertUser(Map<String, Object> map) {
  userServerMapper.insert(map);
  return "insertUser success";
  }
  
   //fegin调用user-server服务
  @Autowired
  private UserFegin userFegin;
  //对money表操作mapper
  @Autowired
  private MoneyServerMapper moneyServerMapper;
  /**
  * user-server
  * @Auhotr:SimpleWu
  * @TxTransaction 使用该注解启动分布式事务
  * @Transactional 同时使用spring事务开启本地事务
  * 插入一个用户
  */
  @Override
  @TxTransaction
  @Transactional
  public String insert() {
  String userId = UUID.randomUUID().toString();
  Map<String,Object> param = new HashMap<>();
  param.put("ID",userId);
  param.put("USER_ID",userId);
  param.put("MONEY",100);
  param.put("USERPASS","12321321");
  //先调用远程服务测试事务回滚
  System.out.println( userFegin.hello("张三","12321321",userId));
  int i = 0 / 0;
  moneyServerMapper.insert(param);
  return "success " + param;
  }
   启动顺序:
  部署Redis
  部署TM的Jar包
  部署Eureka服务注册中心
  部署user-server服务
  部署money-server服务
  忽略网关等.....
  访问money-server服务 :http://localhost:13000/hello 调用 insert();
 int i = 0 / 0;
  该行代码发生异常,UserFegin为user-server远程放服务调用后打印"insertUser success"代表调用成功,如果分布式事务没有效果,那么遇见该异常远程方不会进行回滚。
  在本次测试是回滚成功的,就不贴图了,亲自尝试才能体会到,那种感觉。
  然后删除money-server中删除int i = 0 / 0;重新启动。
  再次调用http://localhost:13000/hello调用 insert(),成功插入两条数据。
  访问:http://localhost:7970进入TxManager系统后台,登录密码是我们设置的123456。里面可以看到配置信息,以及异常信息日志,系统日志。
  该篇案例源代码与工具见:https://github.com/450255266/open-doubi

      上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号