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

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 技术经验解读:三种分布式事务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版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
7天前
|
SQL NoSQL 数据库
SpringCloud基础6——分布式事务,Seata
分布式事务、ACID原则、CAP定理、Seata、Seata的四种分布式方案:XA、AT、TCC、SAGA模式
SpringCloud基础6——分布式事务,Seata
|
7天前
|
人工智能 Kubernetes Cloud Native
深度对话 解锁阿里云分布式云原生技术落地新姿势
深度对话 解锁阿里云分布式云原生技术落地新姿势
深度对话 解锁阿里云分布式云原生技术落地新姿势
因为一个问题、我新学了一门技术 ElasticSearch 分布式搜索
这篇文章讲述了作者因为一个检索问题而学习了ElasticSearch技术,并分享了排查和解决ElasticSearch检索结果与页面展示不符的过程。
因为一个问题、我新学了一门技术 ElasticSearch 分布式搜索
|
26天前
|
存储 缓存 负载均衡
【PolarDB-X 技术揭秘】Lizard B+tree:揭秘分布式数据库索引优化的终极奥秘!
【8月更文挑战第25天】PolarDB-X是阿里云的一款分布式数据库产品,其核心组件Lizard B+tree针对分布式环境优化,解决了传统B+tree面临的数据分片与跨节点查询等问题。Lizard B+tree通过一致性哈希实现数据分片,确保分布式一致性;智能分区实现了负载均衡;高效的搜索算法与缓存机制降低了查询延迟;副本机制确保了系统的高可用性。此外,PolarDB-X通过自适应分支因子、缓存优化、异步写入、数据压缩和智能分片等策略进一步提升了Lizard B+tree的性能,使其能够在分布式环境下提供高性能的索引服务。这些优化不仅提高了查询速度,还确保了系统的稳定性和可靠性。
54 5
|
27天前
|
消息中间件 存储 NoSQL
MQ的顺序性保证:顺序队列、消息编号、分布式锁,一文全掌握!
【8月更文挑战第24天】消息队列(MQ)是分布式系统的关键组件,用于实现系统解耦、提升可扩展性和可用性。保证消息顺序性是其重要挑战之一。本文介绍三种常用策略:顺序队列、消息编号与分布式锁,通过示例展示如何确保消息按需排序。这些方法各有优势,可根据实际场景灵活选用。提供的Java示例有助于加深理解与实践应用。
44 2
|
1月前
|
关系型数据库 MySQL 数据库
SpringCloud2023中使用Seata解决分布式事务
对于分布式系统而言,需要保证分布式系统中的数据一致性,保证数据在子系统中始终保持一致,避免业务出现问题。分布式系统中对数据的操作要么一起成功,要么一起失败,必须是一个整体性的事务。Seata简化了这个使用过程。
47 2
|
20天前
|
C# UED 定位技术
WPF控件大全:初学者必读,掌握控件使用技巧,让你的应用程序更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,控件是实现用户界面交互的关键元素。WPF提供了丰富的控件库,包括基础控件(如`Button`、`TextBox`)、布局控件(如`StackPanel`、`Grid`)、数据绑定控件(如`ListBox`、`DataGrid`)等。本文将介绍这些控件的基本分类及使用技巧,并通过示例代码展示如何在项目中应用。合理选择控件并利用布局控件和数据绑定功能,可以提升用户体验和程序性能。
37 0
|
27天前
|
消息中间件 监控 RocketMQ
分布式事务实现方案:一文详解RocketMQ事务消息
分布式事务实现方案:一文详解RocketMQ事务消息
|
29天前
|
SQL 存储 分布式计算
神龙大数据加速引擎MRACC问题之RDMA技术帮助大数据分布式计算优化如何解决
神龙大数据加速引擎MRACC问题之RDMA技术帮助大数据分布式计算优化如何解决
24 0
|
30天前
|
存储 监控 开发者
分布式链路监控系统问题之系统拆分后链路追踪技术的问题如何解决
分布式链路监控系统问题之系统拆分后链路追踪技术的问题如何解决

热门文章

最新文章