在soa的架构中,假设有注册用户服务A,A做的事很简单,就是insert一条记录到user表,并且调用赠送用户积分服务B,B做的事也很简单,insert一条记录到coin表。服务A和B是分别部署在两台不同的机器,有可能发生的一种情况就是A在调用B的时候,B插入coin表一条记录并返回成功标志通过网络传输给A,假设在网络传输中,网络堵塞,这时A调用B的结果就是超时失败,A将会回滚user表,但此时B服务的coin表是成功插入记录的,这样就出现数据不一致了。也正因为网络是不可靠的,分布式要面临很多问题。
1 JTA(XA)事务【二阶段提交】
对于一个应用一个数据源这种情况,使用传统的jdbc事务,conn.commit()提交,conn.rollback()回滚,在conn的生命周期内事务有效,对应的是java.sql.*。
对于一个应用多个数据源这种情况,jdbc事务就不行了,只能使用JTA事务了,对应的的是javax.transaction.*。实际上jta的底层是xa协议,必须使用支持xa的数据库连接驱动,对应的是javax.sql.*。
XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。
用JTA界定事务,那么就需要有一个实现javax.sql.XADataSource,javax.sql.XAConnection和javax.sql.XAResource接口的JDBC驱动程序。一个实现了这些接口的驱动程序将可以参与JTA事务。一个XADataSource对象就是一个XAConnection对象的工厂。XAConnection是参与JTA事务的JDBC连接。要使用JTA事务,必须使用XADataSource来产生数据库连接,产生的连接为一个XA连接。XA连接(javax.sql.XAConnection)和非XA(java.sql.Connection)连接的区别在于:XA可以参与JTA的事务,而且不支持自动提交。mysql对应的XADataSource是com.mysql.jdbc.jdbc2.optional.MysqlXADataSource。
一般情况下java ee服务器比如jboss才会支持jta,那如果使用tomcat如何使用JTA呢,有以下两种方式:
(1) 独立的第三方开源JTA实现比如JOTM,Atomikos(可以和spring结合使用)。
(2) 引用应用服务器(如jboss。Tomcat是Servlet容器,但它也提供了JNDI的实现)的JNDI数据源,间接实现JTA事务管理(可以结合srping或hibernate)。
XA协议这种二阶段提交有很强的一致性,肯定会各种资源锁定和互相等待,系统开销比较大,在系统开发过程中应慎重考虑是否确实需要。对于多个独立应用互相调用的情况,也就是开头举的例子,XA就没办法了,下面讲讲对于这种情况的解决方案。
2 TCC(事务补偿机制)
TCC是分布式事务实现的一种方式,分别对应Try、Confirm和Cancel三种操作。TCC其实也算两阶段提交,只是工作在应用层而不是资源层。
Try: 尝试执行业务,
-完成所有业务检查(一致性)。
-预留必须业务资源(准隔离性)。
Confirm: 确认执行业务,
-真正执行业务。
-不作任何业务检查。
-只使用Try阶段预留的业务资源。
-Confirm操作满足幂等性。
Cancel: 取消执行业务,
-释放Try阶段预留的业务资源。
-Cancel操作满足幂等性。
现在已经有一些TCC的开源实现了:
tcc-transaction:https://github.com/changmingxie/tcc-transaction
ByteTCC:https://github.com/liuyangming/ByteTCC
TCC跟业务逻辑结合的比较紧密,开发成本比较高。如果业务需要的不是实时一致性的事务,可以考虑最终一致性的解决方案。
3 基于消息的最终一致性事务
以开头举的例子来说,注册用户服务A除了insert一条记录到user表,同时insert一条积分消息记录到message表,然后启动一个独立进程扫描message表,调用服务B,B返回成功就删除当前message记录,失败了就重试n次,重试多次后仍然失败就只能人工干预处理了。进一步的方案是去掉message表,改成往消息中间件(比如ActiveMQ,RabbitMQ)发消息,这种方案真正实现了两个服务的真正解耦,解耦的关键就是异步消息和消息持久化机制。
A调用服务B的时候,有可能因为网络或者其它原因超时失败(实际上有可能B还在执行中或者已经执行成功),A就会发起第二次调用,这就可能导致最后coin表里有几条重复的积分记录。所以接口B需要满足幂等性(可以A生成coin表的id主键然后传给B,由数据库来保证),幂等性是指业务方法重复调用多次产生的业务结果与调用一次产生的业务结果相同,简单点讲所有提供的业务服务,不管是正向还是逆向的业务服务,都必须要支持重试。因为服务调用失败这种异常必须考虑到,不能因为服务的多次调用而导致业务数据的累计增加或减少。
幂等性的实现方式可以是:
(1) 通过唯一键值做处理,即每次调用的时候传入唯一键值,通过唯一键值判断业务是否被操作,如果已被操作,则不再重复操作。
(2) 通过状态机处理,给业务数据设置状态,通过业务状态判断是否需要重复执行。
推荐一些文章:
详解Mysql分布式事务XA(跨数据库事务):http://blog.csdn.net/soonfly/article/details/70677138
数据库三种连接PooledConnection,XAConnection,Connection(连接三剑客):http://blog.csdn.net/turkeyzhou/article/details/3071683
如何用消息系统避免分布式事务:http://blog.jobbole.com/89140/
说说分布式事务(三):https://segmentfault.com/a/1190000005969526
Java事务与JTA:http://blog.csdn.net/codepest/article/details/8437661
JTA 深度历险 - 原理与实现:https://www.ibm.com/developerworks/cn/java/j-lo-jta/index.html
TCP三次握手、四次握手内容整理:https://blog.csdn.net/qq_18425655/article/details/52163228
补充:其实最好的分布式事务解决方案就是不要分布式事务,如果出现了分布式事务,说明服务的业务领域划分是不合理的。服务化架构是一套松耦合的架构,服务的拆分原则是服务内部高内聚,服务之间低耦合。
感谢阅读!!!
相关推荐
Java分布式事务是大型分布式系统中不可或缺的一个重要组成部分,它确保在多个网络节点间的数据操作能够保持一致性和完整性。在分布式环境中,由于多个服务之间可能存在数据交互,因此需要一种机制来处理跨服务的数据...
本文来自于csdn,本文主要从分布式的原因,事务特性,和解决方案中深入理解了分布式事务,希望对您的学习有所帮助。 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的...
### 深入理解分布式事务 #### 一、分布式事务定义及重要性 分布式事务是指在分布式系统中,为了确保跨多个节点上的操作能够正确地完成或者全部回滚,所采取的一种事务处理机制。在这样的场景下,事务的参与者、...
SpringBoot作为一款轻量级的框架,提供了便捷的多数据源配置和分布式事务管理方案,使得开发者能够高效地管理和操作不同的数据库。本文将详细探讨SpringBoot如何实现多数据源以及分布式事务。 首先,我们要理解什么...
### 分布式事务若依框架文档 #### 一、分布式事务基本概念 在理解分布式事务之前,我们首先需要了解数据库事务的基本属性,即ACID特性。 - **原子性(Atomicity)**:事务中的所有操作要么全部成功,要么全部失败...
TCC(Try-Confirm-Cancel)模式是一种著名的分布式事务解决方案,它适用于大型微服务架构。本资料"基于Hyperf框架的TCC分布式事务组件"旨在帮助开发者理解如何在Hyperf这个高性能、轻量级的PHP微服务框架中实现TCC...
"浅谈分布式事务实现技术及应用场景探讨" 分布式事务是指在分布式系统中,多个节点之间的数据访问和更新操作集合,需要保证事务的原子性、一致性、隔离性和持久性。随着软件系统支持用户数的不断提高,对其架构的...
本项目"java+spring+mybatis+mysql+RuoYi-atomikos-实现分布式事务.zip"是一个基于若依(RuoYi)框架改造的多模块分布式事务解决方案,它利用了Atomikos这一强大的分布式事务管理器。以下将详细解析这个项目的知识点...
分布式事务是一个绕不过去的挑战!微服务架构本质上就是分布式服务化架构,微服务架构的流行,让分布式事务问题日益突出!尤其是在订单业务、资金业务等系统核心业务流程中,一定要有可靠的分布式事务解决方案来保证...
《若依框架分布式事务配置与项目启动指南》 在当今的互联网时代,高并发、大数据量的业务场景对系统的性能和稳定性提出了更高要求,而分布式事务则是解决这些问题的关键技术之一。若依框架作为一款广受欢迎的Java...
在大规模的SOA(Service-Oriented Architecture,面向服务架构)系统中,分布式事务处理是一项至关重要的技术。这种架构通常涉及多个独立的服务协同工作,每个服务都可能有自己的数据存储,因此,确保这些服务之间的...
在IT行业中,分布式事务处理是复杂系统架构中的一个重要环节,特别是在多数据库或服务协同工作的场景下。本项目“spring+jotm+ibatis+mysql实现JTA分布式事务”旨在利用这些技术来确保在分布式环境中的数据一致性。...
分布式事务是一种在分布式系统中处理数据一致性的重要技术。在大型网络应用中,数据往往分散在多个数据库或服务器上,为了保证这些数据的一致性,就需要使用分布式事务来协调跨多个节点的操作。本资料包“分布式事务...
该项目是一个采用消息队列解决分布式事务的开源框架,基于Java语言开发(JDK1.8),并支持dubbo、springcloud、motan等RPC框架进行分布式事务处理。通过该项目,开发者可以学习并实践分布式事务的处理,为后续的...
【ejb3.0 分布式事务详解】 在企业级Java应用中,EJB(Enterprise JavaBeans)3.0提供了一种强大而灵活的方式来处理分布式事务。分布式事务是指跨越多个数据库或资源管理器的单一逻辑操作,确保了数据的一致性和...
分布式事务与Seata 分布式事务是指在分布式系统中跨多个资源或服务进行的交易操作,需要保证操作的原子性、一致性、隔离性和持久性。分布式事务的解决方案包括Seata、TCC、SAGA、X/Open XA等。 分布式事务的产生是...
分布式事务是为了解决分布式系统中跨越多个节点的操作,要求这些操作要么全部成功要么全部失败的一种事务机制。它是为了保证在不同节点上的数据一致性而产生的概念。分布式事务广泛应用于微服务架构、数据库分库分表...