技术经验解读:三种分布式事务LCN、Seata、MQ

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 技术经验解读:三种分布式事务LCN、Seata、MQ

分布式事务存在的原因:数据分布在不同的数据库实例。一个分布式系统下存在多个模块协调来完成一次业务,每一个模块对应一个数据源,同一个业务需要操作不同的模块,改动不同的数据库,要么都成功,要么都失败。


举例:


去A库中存储老师实体类的数据


?1234567@Datapublic class Teacher{ @Id private Integer tid; @Field private String tname;}


去B库中存储学生实体类的数据


?12345678910@Data@Documentpublic class Teacher{ @Id private String id; @Field privtae String name; @Field private Integer tid;}


这两个pojo类通过tid关联,学生对老师是一对多的关系,两个POJO的数据通过mysql存储在两个不同的类。


常见的分布式框架解决方案


全局事务2pc --关系型数据库


缺点:效率低,算法执行过程中,所有的节点处于阻塞状态,所有节点所持有的资源处于封锁状态。


3pc(三段提交协议)


消息中间件


提供回滚接口


为了方便我们了解分布式事务框架,我们需要先了解的相关说明。


Spring本地事务是在同一个系统里做的实务操作,需要符合数据库事务ACID特性,为刚性事务;而分布式事务往往不能满足ACID,不同的数据库实例对同一个方法在一个时间的响应并不完全一样,但可能最终一致,这种事务是柔性事务。


柔性事务定理了解


1. CAP定理


一个分布式系统于事务由三个特性:Consistency(一致性) 、Availability(可用性)、 Partition tolerance(分区容错性)。现实情况下,分布式系统最多同时满足其中两个,不能同时满足三个。


可用性和一致性是矛盾的,原因是在分布式事务中操作多个节点的时候,一个节点坏了还得有别的节点来承担,这是为了满足可用性,但不符合一致性。


分区容错性意思是,系统不能在一定时限内达到数据的一致性,就意味着发生了分区的情况。假设在一定时间内,A节点和C节点没能同步数据,那么框架需要决定到底是A版本还是C版本作为后续操作数据的基版。


2. BASE理论


CAP理论的优化。Basically Available(基本可用 )、soft state(软状态),Eventually consistent(最终一致性)三个短语的缩写。


BASE理论要求,即使无法做到节点强一致,但每个分布式应用都可以根据自身业务特点,采用适当的方式达到最终一致性。


BA基本可用:指分布式系统中出现不可知故障的时候,允许损失部分可用性,但不代表整个系统不可用。(比如秒杀活动的并发降级页面)


S软状态:系统中数据允许存在中间状态(软状态),并认为这个状态不影响可用性,允许分布式节点之间存在同步延迟。(如Eureka集群同步数据)


最终一致性:允许整个系统数据在经过一定时间后,最终能达到整个系统的一致性。为弱一致性,响应给用户结果时整个系统没有达到一致性,但最终一定会达到一致性的。


强一致性:系统接受请求后,整个系统必须达到一致的结果才能响应。


根据不同的解决方案衍生出了不同的分布式事务技术,下面介绍不同的分布式技术在这个示例的表现。


LCN


介绍


XA两阶段提交协议


第一阶段所有的参与者TC(Transaction Client)准备执行事务并锁住需要的资源,并向事务管理器报备自己已经准备好。


第二阶段事务管理器负责协调,向不同的RM(资源管理器)索要数据,尽可能晚提交事务(在提交之前完成所有的工作),但也要等待TM(Transaction Manager)响应容易阻塞。吞吐量优先,不适合互联网。


三种模式


基于XA两阶段提交协议,现存LCN分布式事务框架有三种模式,分别是LCN模式,TCC模式,TXC模式。


1. LCN模式:基于jdbc关系型数据库实现对本地事务的操作,然后在由TM(Transaction Manager)统一协调控制事务。当本地事务提交回滚或者关闭连接时将会执行假操作,该代理的连接将由LCN连接池管理。基于注解 @LcnTransaction。


2. TCC模式:基于非关系型数据库(非关系型就是非事务性,除此之外也支持关系型数据库),相对于传统事务机制(X/Open XA Two-Phase-Commit),其特征在于它不依赖资源管理器(RM)对XA的支持,而是通过对(由业务系统提供的)业务逻辑的调度来实现分布式事务。主要由三阶段完成,Try: 尝试执行业务、 Confirm:确认执行业务、 Cancel: 取消执行业务。特点:完全依赖开发者,通过重写三个方法来实现对事务的控制,基于注解@TccTransaction。


3. TXC模式:命名来源于淘宝,实现原理是在执行SQL之前,先查询SQL的影响数据,然后保存执行的SQL快走信息和创建锁。当需要回滚的时候就采用这些记录数据回滚数据库,目前锁实现依赖redis分布式锁控制。特点:嵌入低,不会占用数据库的连接资源,资源消耗较多,基于注解@TxcTransaction。


LCN原理解析


事务发起方和参与方都属于TxClient,TxManager负责控制整个事务。


123代表三个txClient将自己的事务发布到TxManager,4为发起方告诉txManager获取数据成功或者失败,如果成功(其中一个失败也算失败),TxManager返回通知AB让他们各自提交自己的事务。5为txManager通知发起方提交自己的事务。


LCN事务核心步骤


1. 创建事务组:事务发起方在开始执行业务代码之前先调用txManager创建事务组对象,拿到事务表示GroupId。


2. 加入事务组:2和3,参与方将自己的事务执行情况报备给txManager


3. 通知事务组:发起方执行完业务代码之后,将执行结果状态通知给txManager


4. 通知事务单元:txManager询问参与方的事务执行结果


5. 响应通知事务组:txManager通知发起方事务的最终结果


配置Tx-LCN案例


一、新建


1. 执行依赖中带有的tx-manager.sql文件到数据库中


2. 配置application.properties


TC配置


# 是否启动LCN负载均衡策略(优化选项,开启与否,功能不受影响)


tx-lcn.ribbon.loadbalancer.dtx.enabled=true


# tx-manager 的配置地址,可以指定TM集群中的任何一个或多个地址


# tx-manager 下集群策略,每个TC都会从始至终[/span>断线重连

# TM方,每有TM进入集群,会找到所有TC并通知其与新TM建立连接。


# TC方,启动时按配置与集群建立连接,成功后,会再与集群协商,查询集群大小并保持与所有TM的连接


tx-lcn.client.manager-address=127.0.0.1:8070


# 该参数是分布式事务框架存储的业务切面信息。采用的是h2数据库。绝对路径。该参数默认的值为{user.dir}/.txlcn/{application.name}-{application.port}


tx-lcn.aspect.log.file-path=logs/.txlcn/demo-8080


# 调用链长度等级,默认值为3(优化选项。系统中每个请求大致调用链平均长度,估算值。)


tx-lcn.client.chain-level=3


# 该参数为tc与tm通讯时的最大超时时间,单位ms。该参数不需要配置会在连接初始化时由tm返回。


tx-lcn.client.tm-rpc-timeout=2000


# 该参数为分布式事务的最大时间,单位ms。该参数不允许TC方配置,会在连接初始化时由tm返回。


tx-lcn.client.dtx-time=8000


# 该参数为雪花算法的机器编号,所有TC不能相同。该参数不允许配置,会在连接初始化时由tm返回。


tx-lcn.client.machine-id=1


# 该参数为事务方法注解切面的orderNumber,默认值为0.


tx-lcn.client.dtx-aspect-order=0


# 该参数为事务连接资源方法切面的orderNumber,默认值为0.


tx-lcn.client.resource-order=0


# 是否开启日志记录。当开启以后需要配置对应logger的数据库连接配置信息。


tx-lcn.logger.enabled=false


tx-lcn.logger.driver-class-name=${spring.datasource.driver-class-name}


tx-lcn.logger.jdbc-url=${spring.datasource.url} #jdbc:mysql://localhost:3306/tx-manager?characterEncoding=UTF-8 遇上servertimezone问题添加serverTimezone=GMT


tx-lcn.logger.username=${spring.datasource.username}


tx-lcn.logger.password=${spring.datasource.password}


tx-lcn.logger.enabled=false #如果打开事务:更改 tx-lcn.logger.enabled=true


TM配置


spring.application.name=TransactionManager


server.port=7970


# JDBC 数据库配置


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=123456


# 数据库方言


spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect


# 第一次运行可以设置为: create, 为TM创建持久化数据库表


spring.jpa.hibernate.ddl-auto=validate


# TM监听IP. 默认为 127.0.0.1


tx-lcn.manager.host=127.0.0.1


# TM监听Socket端口. 默认为 ${server.port} - 100


tx-lcn.manager.port=8070


# 心跳检测时间(ms). 默认为 300000


tx-lcn.manager.heart-time=300000


# 分布式事务执行总时间(ms). 默认为36000


tx-lcn.manager.dtx-time=8000


# 参数延迟删除时间单位ms 默认为dtx-time值


tx-lcn.message.netty.attr-delay-time=${tx-lcn.manager.dtx-time}


# 事务处理并发等级. 默认为机器逻辑核心数5倍


tx-lcn.manager.concurrent-level=160


# TM后台登陆密码,默认值为codingapi


tx-lcn.manager.admin-key=codingapi


# 分布式事务锁超时时间 默认为-1,当-1时会用tx-lcn.manager.dtx-time的时间


tx-lcn.manager.dtx-lock-time=${tx-lcn.manager.dtx-time}


# 雪花算法的sequence位长度,默认为12位.


tx-lcn.manager.seq-len=12


# 异常回调开关。开启时请制定ex-url


tx-lcn.manager.ex-url-enabled=false


# 事务异常通知(任何http协议地址。未指定协议时,为TM提供内置功能接口)。默认是邮件通知


tx-lcn.manager.ex-url=/provider/email-to/**@.com


# 开启日志,默认为false


tx-lcn.logger.enabled=true


tx-lcn.logger.enabled=false


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}


# redis 的设置信息. 线上请用Redis Cluster


spring.redis.host=127.0.0.1


spring.redis.port=6379


spring.redis.password=


配置本地事务和分布式事务


@Configuration


@EnableTransactionManagement


public class TransactionConfiguration {


/


本地事务配置


@param transactionManager


@return


/


@Bean


@ConditionalOnMissingBean


public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {


Properties properties = new Properties();


properties.setProperty("", "PROPAGATION_REQUIRED,-Throwable");


TransactionInterceptor transactionInterceptor = new TransactionInterceptor();


transactionInterceptor.setTransactionManager(transactionManager);


transactionInterceptor.setTransactionAttributes(properties);


return transactionInterceptor;


}


/**


分布式事务配置 设置为LCN模式


@param dtxLogicWeaver


@return


/


@ConditionalOnBean(DTXLogicWeaver.class)


@Bean


public TxLcnInterceptor txLcnInterceptor(DTXLogicWeaver dtxLogicWeaver) {


TxLcnInterceptor txLcnInterceptor = new TxLcnInterceptor(dtxLogicWeaver);


Properties properties = new Properties();


properties.setProperty(Transactions.DTX_TYPE,Transactions.LCN);


properties.setProperty(Transactions.DTX_PROPAGATION, "REQUIRED");


txLcnInterceptor.setTransactionAttributes(properties);


return txLcnInterceptor;


}


@Bean


public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {


BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();


//需要调整优先级,分布式事务在前,本地事务在后。


beanNameAutoProxyCreator.setInterceptorNames("txLcnInterceptor","transactionInterceptor");


beanNameAutoProxyCreator.setBeanNames("Impl");


return beanNameAutoProxyCreator;


}


}


二、依赖


TX-Manager配置,独立于微服务,是独立的依赖


[/span>dependencies

[/span>dependency

[/span>groupId

[/span>artifactId


[/span>dependency

[/span>groupId

[/span>artifactId


[/span>dependency

[/span>groupId

[/span>artifactId

[/span>scope


[/span>dependency

[/span>groupId

[/span>artifactId

[/span>version



[/span>dependencyManagement

[/span>dependencies

[/span>dependency

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
17天前
|
监控 数据可视化 Java
【JAVA】分布式链路追踪技术概论
【JAVA】分布式链路追踪技术概论
27 2
|
2天前
|
NoSQL 前端开发 Java
技术笔记:springboot分布式锁组件spring
技术笔记:springboot分布式锁组件spring
|
2天前
|
NoSQL 算法 Java
技术好文:Redis实现分布式锁的7种方案
技术好文:Redis实现分布式锁的7种方案
|
15天前
|
Java 数据库 开发者
深入解析 Spring Cloud Seata:分布式事务的全面指南
深入解析 Spring Cloud Seata:分布式事务的全面指南
35 1
|
17天前
|
存储 消息中间件 Java
【分布式链路追踪技术】sleuth+zipkin
【分布式链路追踪技术】sleuth+zipkin
21 1
|
18天前
|
存储 Kubernetes 监控
etcd:分布式键值存储系统技术
`etcd` 是一个用于共享配置和服务发现的高度可用键值存储系统,基于Raft算法保证数据一致性。它提供HTTP/GRPC API,常用于服务发现、配置共享和分布式锁。etcd集群包含多个节点,每个节点可为领导者或跟随者。在Kubernetes中,etcd存储集群状态,其稳定性和一致性至关重要。维护etcd涉及备份、状态监控、日志审计和安全措施。
25 2
|
2天前
|
存储 Java C++
技术心得记录:分布式文件系统KFS基础知识介绍
技术心得记录:分布式文件系统KFS基础知识介绍
|
8天前
|
供应链 监控 物联网
区块链通过其独特的分布式账本技术和智能合约功能,确保供应链信息的实时更新
**区块链技术革新供应链:分布式账本确保信息实时一致,智能合约自动执行降低错误,物联网追踪增强透明度和信任。通过去中心化、不可篡改的特性,实现交易验证、货物追踪与业务规则自动化,提升供应链效率与安全性。**
|
8天前
|
消息中间件 SQL 关系型数据库
分布式事务-seata
分布式事务-seata
21 0
|
17天前
|
存储 大数据 Linux
【大数据】GFS,大数据技术的基石,分布式文件系统的鼻祖
【大数据】GFS,大数据技术的基石,分布式文件系统的鼻祖
27 0