【分布式事务框架TX-LCN】
六、TxManager搭建
1. 创建项目,添加依赖
新建项目TxManager,并添加依赖。
依赖包含了Spring-boot的依赖,版本是2.0.5,如果希望把版本改变成2.2.2或其他版本只需要添加spring-boot-starter-parent继承即可
![d531024a3e6fd0952f6171726e51b0c0.png](https://img-blog.csdnimg.cn/img_convert/d531024a3e6fd0952f6171726e51b0c0.png)
2. 执行SQL文件
执行tx-manager.sql文件(在任意的数据库下执行即可)
tx-manager.sql在txlcn-tm-5.0.2.RELEASE.zip压缩包中。
在MySQL生成tx-manager的数据库,在数据库中新建t_tx_exception的表,此表用作存储事务组信息。
注意:
默认情况下tx-manager需要记录日志信息的,需要在项目中配置日志连接数据库相关参数,其中日志存储数据库没有要求,可以存储到任意数据库中,当运行后会自动在数据库中生成一个日志表。如果不希望记录日志可以直接设置tx-lcn.logger.enabled=false,关闭日志功能,下面的日志连接数据库参数也可以不用配置。
在实际案例演示中会把所有的日志记录功能关闭。如果希望记录记录日志需要把下面代码在所有引用tx-lcn的项目的配置文件中进行配置。
![9c26c7bbe6ce7a315fc23d8b92bc6463.png](https://img-blog.csdnimg.cn/img_convert/9c26c7bbe6ce7a315fc23d8b92bc6463.png)
3. 配置配置文件
在TxManager项目的resource下新建application.properties。tx-lcn在当前版本有个bug只能使用properties文件,使用yml文件会导致配置文件无法被加载的问题。
配置文件中内容上半部分是tx-manager数据库的连接信息。中间包含redis连接信息(此处连接的是redis单机版,端口默认,没有密码),下面是关闭日志记录功能
小提示:
依赖Redis,所以需要安装Redis。
7970是客户端访问端口,是Txmanager可视化界面访问端口,此端口任意。
更加详细配置信息可以看txlcn-tm-5.0.2.RELEASE.zip中application.properties
![f83a51246ef8ecfab33fac9b19029b2d.png](https://img-blog.csdnimg.cn/img_convert/f83a51246ef8ecfab33fac9b19029b2d.png)
4. 新建启动类
注意注解@EnableTrasactionManagerServer必须有。
![117ce0b505861d17259fbf1ce6b9080d.png](https://img-blog.csdnimg.cn/img_convert/117ce0b505861d17259fbf1ce6b9080d.png)
5. 访问管理界面
在浏览器输入:http://localhost:7970 访问。
密码默认是codingapi
可以在配置文件中修改登录密码
![fa29f557f818179d0dfb9a30bd057e15.png](https://img-blog.csdnimg.cn/img_convert/fa29f557f818179d0dfb9a30bd057e15.png)
![3611c4ae31e3bea90a5604db8d0a1389.png](https://img-blog.csdnimg.cn/img_convert/3611c4ae31e3bea90a5604db8d0a1389.png)
七、LCN事务模式
1. 创建数据库表
注意:不要给student表添加外键约束。如果添加会导致分布式事务执行时student新增失败,因为teacher没有提交时student的tid值无法获取。
![7de1549d8420479d2214af324a94a753.png](https://img-blog.csdnimg.cn/img_convert/7de1549d8420479d2214af324a94a753.png)
2. 创建项目
案例使用聚合项目进行演示。
创建父项目,名称为LcnParent
2.1 配置pom.xml
txlcn-tc 是TX-LCN的客户端包
txlcn-txmsg-netty 是LCN客户端连接TxManager需要的包
![d3025c688fdc2079c252f56a9a456cfd.png](https://img-blog.csdnimg.cn/img_convert/d3025c688fdc2079c252f56a9a456cfd.png)
3. 新建pojo项目
把实体类提出了
新建两个实体类。
新建com.bjsxt.pojo.Teacher
![ef79d13981ac5c99ea701e016e9eb45c.png](https://img-blog.csdnimg.cn/img_convert/ef79d13981ac5c99ea701e016e9eb45c.png)
新建com.bjsxt.pojo.Student
![31c2f43eaa11fa907eb36f35d056f822.png](https://img-blog.csdnimg.cn/img_convert/31c2f43eaa11fa907eb36f35d056f822.png)
4. 创建项目teacher_insert
新建teacher_insert项目
4.1 配置pom.xml
依赖pojo
![b3c19c51f002d1a316ed22c136cb0d00.png](https://img-blog.csdnimg.cn/img_convert/b3c19c51f002d1a316ed22c136cb0d00.png)
4.2 编写配置文件
新建application.yml.
数据源连接的是Teacher表所在数据库
eureka单机版可以省略。
manager-address 配置TxManager项目的ip及端口。端口是内部访问端口,而不是可视化页面的端口。
![50d406b593ba6477d19fc798c53f36ed.png](https://img-blog.csdnimg.cn/img_convert/50d406b593ba6477d19fc798c53f36ed.png)
4.3 新建mapper
新建com.bjsxt.mapper.TeacherMapper
![676066f6a7ad2fcfcc3e83ab9f0ed0f0.png](https://img-blog.csdnimg.cn/img_convert/676066f6a7ad2fcfcc3e83ab9f0ed0f0.png)
4.4 新建service及实现类
新建com.bjsxt.service.TeacherService及实现类。
方法上@Transactional一定要有。本地事务控制。
@LcnTransaction表示当前方法加入到分布式事务控制。
@LcnTransaction属性propagation可取值
DTXPropagation.REQUIRED:默认值,表示如果当前没有事务组创建事务组,如果有事务组,加入事务组。多用在事务发起方。
DTXPropagation.SUPPORTS:如果当前没有事务组以本地事务运行,如果当前有事务组加入事务组。多用在事务参与方法。
![7f18f5633f75590a13a2c8e240c41433.png](https://img-blog.csdnimg.cn/img_convert/7f18f5633f75590a13a2c8e240c41433.png)
![f5d3f86351d2333312d5add2920f1f4f.png](https://img-blog.csdnimg.cn/img_convert/f5d3f86351d2333312d5add2920f1f4f.png)
4.5 新建控制器
新建com.bjsxt.controller.TeacherController。
由于在student_insert中通过OpenFeign进行条件,参数使用请求体数据,所以控制器方法的参数需要添加@RequestBody
![2f7ecfc4d0c02a45970aecaa1adf87aa.png](https://img-blog.csdnimg.cn/img_convert/2f7ecfc4d0c02a45970aecaa1adf87aa.png)
4.6 新建启动器
新建com.bjsxt.TeacherInsertApplication。
一定要有注解@EnableDistributedTransaction表示启动分布式事务
![6eb1dff18288acbfa954245a6f1f4a97.png](https://img-blog.csdnimg.cn/img_convert/6eb1dff18288acbfa954245a6f1f4a97.png)
5 新建项目student_insert
5.1 编写pom.xml
添加对pojo依赖
![210bb9782e116b8fb9eedaa5b22cf351.png](https://img-blog.csdnimg.cn/img_convert/210bb9782e116b8fb9eedaa5b22cf351.png)
5.2 创建配置文件
新建application.yml
![a590b13a27b0d457476bdb169cff04c7.png](https://img-blog.csdnimg.cn/img_convert/a590b13a27b0d457476bdb169cff04c7.png)
5.3 新建Feign接口
新建com.bjsxt.feign.TeacherInsertFeign
![d4419066fc8cc24fb737471f71f32269.png](https://img-blog.csdnimg.cn/img_convert/d4419066fc8cc24fb737471f71f32269.png)
5.4 新建Mapper
新建com.bjsxt.mapper.StudentMapper
![d99e0bc2c4b60d350bff281381901807.png](https://img-blog.csdnimg.cn/img_convert/d99e0bc2c4b60d350bff281381901807.png)
5.5 新建service及实现类
新建com.bjsxt.service.StudentService。
实现类中对Teacher和Student的主键都是随机数,为了测试时多次测试方便,所以没有给固定值。
Student的姓名通过客户端请求参数传递的,其他都不需要通过参数设置。
![73a9293235132fece046e72ca1714a7f.png](https://img-blog.csdnimg.cn/img_convert/73a9293235132fece046e72ca1714a7f.png)
![92aade253366b9a66c24a1795f1f8ff9.png](https://img-blog.csdnimg.cn/img_convert/92aade253366b9a66c24a1795f1f8ff9.png)
5.6 新建控制器
新建com.bjsxt.controller.StudentController
![029bc4112936711515614f8da06f817d.png](https://img-blog.csdnimg.cn/img_convert/029bc4112936711515614f8da06f817d.png)
5.7 新建启动类
新建com.bjsxt.StudentInsertApplication
![be1f5b065cddcb01580d93c3acac325d.png](https://img-blog.csdnimg.cn/img_convert/be1f5b065cddcb01580d93c3acac325d.png)
6. 测试结果
在浏览器中输入http://localhost:8081/insert?name=bjsxt后,如果页面显示1并且数据库teacher表和student表各增加一条数据表示新增成功。
为了测试分布式事务效果,在student_insert项目实现类方法return上面添加int i =5/0; 的算术异常,再次访问url页面会报500,并且数据库中没有新增数据,说明分布式事务成功了。
![d5f97db03d235e7c7cca16ab830cf6b9.png](https://img-blog.csdnimg.cn/img_convert/d5f97db03d235e7c7cca16ab830cf6b9.png)
八、TCC事务模式(多模式混合使用)
在上面LCN事务模式代码基础上进行修改
1. 新建项目mongodb_insert
1.1 修改pom.xml
在当前项目中引入mongodb的依赖。如果在父项目中进行引入,则所有的子项目都需要配置mongodb的相关属性。
![32f69080a20f3969ecbc88e7d10d1f95.png](https://img-blog.csdnimg.cn/img_convert/32f69080a20f3969ecbc88e7d10d1f95.png)
1.2 新建配置文件
新建application.yml。
虽然当前项目是连接Mongodb但是也需要配置MySQL数据源,因为LCN需要在MySQL中记录异常信息等。
配置文件中比别的项目多了MongoDB的配置。
![af8837ef9f15af2dec62cf4bd8a28d38.png](https://img-blog.csdnimg.cn/img_convert/af8837ef9f15af2dec62cf4bd8a28d38.png)
1.3 新建实体类
新建com.bjsxt.pojo.People
![4149a8e91b30efd625606656787072f1.png](https://img-blog.csdnimg.cn/img_convert/4149a8e91b30efd625606656787072f1.png)
1.4 新建service及实现类
新建com.bjsxt.service.PeopleService及实现类。
具有@TccTransaction注解的方法有以下特性
- 可以没有@Transactional
- 如果整个分布式事务所有方法执行都没有异常,会回调名称为:confirm+方法名首字母大写的方法。insert方法的回调方法叫做confirmInsert()。同时方法参数也可以传递给回调方法。
- 只要整个分布式事务中有一个方法出现异常,会回调cancel+方法名首字母大写的回调方法。需要在这个方法中编写事务回滚的业务。
@TccTransaction注解属性说明:
cancelMethod:明确指定失败的回调方法名
confirmMethod:明确指定成功的回调方法名
![ec02221962d54aabb2f5c347b16beb8d.png](https://img-blog.csdnimg.cn/img_convert/ec02221962d54aabb2f5c347b16beb8d.png)
![bb1d571810d9cbd9d60b740c8dccd10b.png](https://img-blog.csdnimg.cn/img_convert/bb1d571810d9cbd9d60b740c8dccd10b.png)
1.5 新建控制器
新建com.bjsxt.controller.PeopleController
![679256b94b136b8e24f613c87d5527e5.png](https://img-blog.csdnimg.cn/img_convert/679256b94b136b8e24f613c87d5527e5.png)
1.6 测试
在浏览器输入 http://localhost:8082/insert?name=sxt 观察mongodb中是否出现了lcn的数据库,数据库中是否出现People的集合,people集合中name属性值为sxt
2. 修改student_insert
2.1 新建feign接口
新建com.bjsxt.feign.MongodbInsertFeign。
为了传递普通表单数据,insert方法参数由@RequestParam。mongodb_insert控制器方法参数就可以使用String name或People进行接收。
![3df3f0876d5cd490d2d2b01406e1c60f.png](https://img-blog.csdnimg.cn/img_convert/3df3f0876d5cd490d2d2b01406e1c60f.png)
2.2 修改service实现类
修改com.bjsxt.service.impl.StudentServiceImpl。
在实现类中调用feign接口的方法。
当前方法依然使用LCN事务模式。方法上面加什么事务模式注解只考虑当前方法本地事务,不考虑调用远程方法的事务。如果当前方法中没有本地事务,全是调用远程方法,那么当前方法使用LCN或TCC事务模式都可以,但是必须要有事务模式,因为如果没有注解就不会想TxManager中创建事务组。
![b2bbed2d924f3c5b2cc5791a6cfdeae3.png](https://img-blog.csdnimg.cn/img_convert/b2bbed2d924f3c5b2cc5791a6cfdeae3.png)
需要更多Java学习资料的小伙伴可以到评论区留言或私信我