分布式事务框架TX-LCN使用记录

目录

1 TX-LCN框架的基本思路

2 遇到的问题记录

2.1 事务提交/回滚失败,锁表问题

2.2 事务补偿失败


微服务架构不可避免的要解决分布式事务的问题,为了避免出现分布式事务,在进行微服务划分的时候,我们一般尽量保证业务操作独立,但是有时候分布式事务又是不可避免的。业界关于分布式事务的处理方案也有几种,网上搜到比较多的就是TX-LCN框架。

官网:https://www.txlcn.org/zh-cn/index.html

1 TX-LCN框架的基本思路

这里借用一张官网流程图

分布式事务框架TX-LCN使用记录_第1张图片

可以看到,整体来说,每个微服务的事务还是由Spring自身处理,只不过,不管对于调用方还是被调用来说,在相关操作处理完之后,事务不会立马提交,而是挂起的状态。等到调用方处理完所有的业务操作之后,调用方会通知tm,tm会通知该事务组对应调用链上的所有tc,提交或者回滚对应的事务

这里有几点需要注意:

(1)tm在通知tc进行事务的回滚和提交时,可能会因为网络或者超时参数配置原因出现失败,如果出现失败,tm会忘t_tx_exception表中插入一条记录,然后自动进行事务补偿,即:重试通知。

(2)TCC模式可以处理非数据库事务方式的“事务”操作,例如A调用B和C,其中C使用的是不支持事务的数据库,此时A和B使用LCN模式,C使用TCC模式,TCC模式会自己重写onConfirm和onCancel方式,即事务的提交和回滚操作需要自己定义,这就为不支持事务的数据库提供了解决方案。

下面记录下使用TX-LCN框架时候遇到的问题以及注意点。

2 遇到的问题记录

2.1 事务提交/回滚失败,锁表问题

问题描述:日志查看都正常,但是就是数据插入失败,而且后续再操作会一直表锁。

默认情况下TC是使用应用名称(spring.application.name)加端口号作为模块名称的。这种情况在单服务情况下没问题,但是如果微服务横向扩展集群部署的时候,就会有问题。例如A服务进行集群部署分为A1和A2。此时在TM上注册的模块名称有两个一模一样的记录。当TM通知的时候,会因为模块名称标识一样,出现该提交的事务没收到提交消息提醒,造成事务一直不提交,表锁的问题。

解决方法:

针对这种方式,官网也有解决办法,可以通过TC模块标识自定义方式来解决

@Component
public class MyModIdProvider implements ModIdProvider
{
    @Value("${eureka.instance.ip-address}")
    private String ip;
    @Value("${server.port}")
    private String port;

    @Override
    public String modId()
    {
        return ip+":"+port;
    }
}

这里贴一个截图,第一条是自定义模块标识,第二条是默认的。

分布式事务框架TX-LCN使用记录_第2张图片

解决了模块标识唯一的问题,也就解决了事务通知混乱的问题,也就没有表锁了。

 

2.2 事务补偿失败

tc和tm之间的通信是通过tcp建立的可靠有保障的长链接,但是通讯总是难免受到网络状况的影响,当tm通知tc时候的时候,tm会自动进行事务补偿,但是测试的过程中,发现事务没有补偿,而且在管理平台上也查看不到相关异常记录,对应的t_tx_exception表中也没有记录。跟踪应用的日志发现,有包jpa的相关异常。查看源码后,发现引起该问题的主要原因是TxException表的生成策略设置的AUTO,AUTO的话主键的生成策略是JPA自己的策略。

分布式事务框架TX-LCN使用记录_第3张图片

但是对应表t_tx_exception的主键是自增,这就造成在出现异常的时候,无法把异常插入到异常表,最终导致事务补偿失败。

解决方案:

修改为IDENTITY然后重新编译下即可。

 

你可能感兴趣的:(Java,后端,微服务)