JeeSite 快速开发平台
官方网站
    • 平台简介
    • 架构特点
    • 技术选型
    • 功能介绍
    • 安装部署
    • 常见问题
    • 目录结构
    • 更新日志
    • Vue 文档
    • BPM 文档
    • Cloud 文档
V4 演示
Vue 演示
💖联系
  • 我要提意见、文档纠错
  • JeeSite 代码库, 请⭐Star关注
  • JeeSite Vue 代码库, 请⭐关注
  • Spring Cloud 微服务架构
  • JeeSite 手机端/移动端
  • Flowable 中国式工作流
  • OAauth2 统一认证服务器
  • 政务内外网环境中间件
  • 访问 ThinkGem 官方博客
  • 点击进入,下拉查看动态
官方网站
    • 平台简介
    • 架构特点
    • 技术选型
    • 功能介绍
    • 安装部署
    • 常见问题
    • 目录结构
    • 更新日志
    • Vue 文档
    • BPM 文档
    • Cloud 文档
V4 演示
Vue 演示
💖联系
  • 我要提意见、文档纠错
  • JeeSite 代码库, 请⭐Star关注
  • JeeSite Vue 代码库, 请⭐关注
  • Spring Cloud 微服务架构
  • JeeSite 手机端/移动端
  • Flowable 中国式工作流
  • OAauth2 统一认证服务器
  • 政务内外网环境中间件
  • 访问 ThinkGem 官方博客
  • 点击进入,下拉查看动态
  • 快速了解

  • 开发手册

  • Vue 开发手册

  • 扩展功能专题

  • 云服务技术架构

    • SaaS架构、多租户
    • 负载均衡、集群、高可用
    • SpringCloud 分布式、微服务
    • 分布式事务Seata、AT模式
    • 分布式事务LCN、柔性事务
      • LCN 是什么?
        • LCN 代理连接特点
        • 推荐观看框架原理视频介绍
      • JeeSite 中如何使用?
        • 配置 TM 服务端
        • 配置 TC 客户端
    • 读写分离、分库分表
  • 技术服务与支持

微服务分布式事务解决方案 TX-LCN 框架

# LCN 是什么?

LCN 框架在2017年6月份发布第一个版本,从开始的1.0,已经发展到了5.0版本。 LCN 名称是由早期版本的 LCN 框架命名,在设计框架之初的1.0 ~ 2.0的版本时框架设计的步骤是如下,各取其首字母得来的LCN命名。

  • 锁定事务单元(lock)
  • 确认事务模块状态(confirm)
  • 通知事务(notify)

LCN 5.0 以后由于框架兼容了 LCN、TCC、TXC 三种事务模式,为了避免区分 LCN 模式,特此将 LCN 分布式事务改名为 TX-LCN 分布式事务框架。

TX-LCN 定位于一款事务协调性框架,框架其本身并不操作事务,而是基于对事务的协调从而达到事务一致性的效果。LCN 并不生产事务,LCN 只是本地事务的协调工。

TX-LCN 支持跨 Web 服务器,微服务之间的 Feign 远程调用,支持集群、熔断。

TX-LCN 文档地址:http://www.txlcn.org/zh-cn/docs/background.html (opens new window)

# LCN 代理连接特点

  • 该模式同样对代码的嵌入性低。
  • 该模式仅限于本地存在连接对象且可通过连接对象控制事务的模块。
  • 该模式下的事务提交与回滚是由本地事务方控制,对于数据一致性上有较高的保障。
  • 该模式缺陷在于代理的连接需要随事务发起方一共释放连接,增加了连接占用的时间。

# 推荐观看框架原理视频介绍

  • 认识分布式事务:https://www.bilibili.com/video/av80626430 (opens new window)
  • 了解 TX-LCN 原理 (一):https://www.bilibili.com/video/av80676649 (opens new window)
  • 了解 TX-LCN 原理 (二):https://www.bilibili.com/video/av80676836 (opens new window)
  • TX-LCN 原理 PDF 版:LCN分布式事务-JN20191229.pdf

综上比较 LCN 对 SQL 上没要求,切无性能影响,代码嵌入性低。

# JeeSite 中如何使用?

JeeSite v4.3+ 全面替换为 Seata 事务。点击 Seata 查看详细文档。

# 配置 TM 服务端

TX-LCN 主要有两个模块,Tx-Client(TC)、Tx-Manager(TM). TC 作为微服务下的依赖,TM 是独立的服务。

修改配置文件 /jeesite-cloud-module-txlcn/../application.yml

1、设置 TM 数据库连接:

spring: 
  # 数据源配置
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jeesite?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  jpa:
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate:
      ddl-auto: update
1
2
3
4
5
6
7
8
9
10
11

上面以 MySQL 举例,其它数据库,Baidu 如:Spring Data JPA Oracle 配置,即可找到相关解决方案。

2、设置 TM 监听IP和端口:

tx-lcn: 
  # 分布式事务管理配置
  manager:
    # TM监听IP. 默认为 127.0.0.1
    host: 127.0.0.1
    # TM监听Socket端口. 默认为 ${server.port} - 100
    port: 8070
1
2
3
4
5
6
7

3、启动 TM 服务

找到 /jeesite-cloud-module-txlcn/../TxLcnApplication.java 类,运行 Application 程序。

启动完成后,浏览器访问:http://127.0.0.1:7970 (opens new window) 密码:thinkgem 即可进入 TM 管理后台。

# 配置 TC 客户端

1、关闭 JTA 开启 LCN 事务

打开分布式统一配置文件 /jeesite-cloud-config/../jeesite-cloud-43/application.yml 如果使用 Nacos 请在 Nacos 里配置该文件。

# 关闭 JTA XA 事务
jdbc:
  jta:
    enabled: false

  # 开启LCN事务
  lcn:
	enabled: true
1
2
3
4
5
6
7
8

JeeSite 里的 JTA (XA) 事务是有 Atomikos 实现的,为了不对 LCN 事务所影响,所以需要关闭 JTA 事务。

2、关闭 Ribbon 的重试机制

打开分布式统一配置文件 /jeesite-cloud-config/../jeesite-cloud-43/application.yml

ribbon:
  MaxAutoRetriesNextServer: 0
1
2

为什么要关闭服务调用的重试。远程业务调用失败有两种可能: (1),远程业务执行失败 (2)、远程业务执行成功,网络失败。对于第 2 种,事务场景下重试会发生,某个业务执行两次的问题。如果业务上控制某个事务接口的幂等,则不用关闭重试。

3、pom.xml 增加依赖

<!-- 分布式事务 -->
<dependency>
    <groupId>com.jeesite</groupId>
    <artifactId>jeesite-cloud-module-txlcn-client</artifactId>
    <version>${project.parent.version}</version>
</dependency>
1
2
3
4
5
6

添加到每个 Web 微服务的 pom.xml 文件中。

4、编写业务测试代码

由于 LCN 代码嵌入性非常低,不需要你关注太多事务方面的东西。开发模式和你本地开发模式一致。

在需要处理事务的方法上添加 @LcnTransaction 注解即可,本地事务注解保留。

JeeSite Cloud 已为你编写好的测试代码,依次打开如下文件:

  • jeesite-cloud-module-core/../TransTestService.java
  • jeesite-cloud-module-test1/../TestDataService.java
  • jeesite-cloud-module-test2/../TestTreeService.java

将每个文件里的 @LcnTransaction 前的 // 注释去掉,并导入包即可

为了方便理解,下面将关键测试代码进行展示,如下:

jeesite-cloud-module-core/../TransTestService.java

/**
 * 事务测试,第二个接口调用故意抛出异常
 */
@LcnTransaction
@Transactional(readOnly=false)
public void transTest(TestData testData) {
	
	// 正常保存 testData 数据
	testData.setIsNewRecord(true);
	testData.setId(IdGen.randomBase62(5));
	testData.setTestInput(testData.getId());
	testData.setTestTextarea(testData.getId());
	testDataService.save(testData);
	
	// 保存 testTree 失败,抛出异常,testData 应回滚
	TestTree testTree = new TestTree();
	testTree.setIsNewRecord(true);
	testTree.setTreeCode(testData.getId());
	testTree.setTreeName(testData.getId());
	TestTree where = new TestTree();
	where.setParentCode(TestTree.ROOT_CODE);
	TestTree last = testTreeService.getLastByParentCode(where);
	if (last != null){
		testTree.setTreeSort(last.getTreeSort()+30);
	}
	// 设置一个超出数据库范围的值,抛出数据库异常
	StringBuilder sb = new StringBuilder();
	for (int i=0; i<500; i++){
		sb.append("transTest" + i);
	}
	testTree.setTreeName(sb.toString());
	testTreeService.save(testTree);
	
	// 有些情况可能需要手动回滚事务,调用该方法即可
	//DTXUserControls.rollbackCurrentGroup();
}

/**
 * 事务验证,返回空,则事务回滚成功
 */
public boolean transValid(TestData testData) {
	if (StringUtils.isBlank(testData.getId())){
		return true;
	}
	return testDataService.get(testData.getId()) == null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

jeesite-cloud-module-core/../TransTestController.java

@Controller
@RequestMapping(value = "${adminPath}/trans")
public class TransTestController extends BaseController {

	@Autowired
	private TransTestService transTestService;
	
	/**
	 * 查询列表数据
	 */
	@RequestMapping(value = "test")
	@ResponseBody
	public String test(TestData testData) {
		try{
			transTestService.transTest(testData);
		}catch (Exception e) {
			logger.debug("事务测试信息,报错回滚:" + e.getMessage(), e);
		}
		boolean bl = transTestService.transValid(testData);
		return renderResult(Global.TRUE, "事务测试"+(bl?"成功,数据已":"失败,数据未")+"回滚!");
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

jeesite-cloud-module-test1/../TestDataService.java

@LcnTransaction
@Transactional(readOnly=false)
public void save(TestData testData) {
		super.save(testData);
}
1
2
3
4
5

jeesite-cloud-module-test2/../TestTreeService.java

@LcnTransaction
@Transactional(readOnly=false)
public void save(TestTree testTree) {
		super.save(testTree);
}
1
2
3
4
5

5、启动各个微服务

访问分布式事务,测试地址:http://127.0.0.1:8980/js/a/trans/test (opens new window)

若提示 “事务测试成功” 即正常运行。

进入 JeeSite 源码仓库页面,点击右上角 ⭐ Star 加星关注。

← 分布式事务Seata、AT模式 读写分离、分库分表→

联系我们:s.jeesite.com  |  微信号:jeesitex  |  邮箱:jeesite@163.com
© 2013-2023 济南卓源软件有限公司 版权所有 | Theme Vdoing

关注 JeeSite 公众号,了解最新动态

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式