欢迎来到 - 微信美文网 !    
当前位置: 首页 > qq日志 > 非主流日志 >

如何实现XA式、非XA式Spring分布式事务

时间:2018-05-21 20:43 点击:
在JavaWorld大会上,来自SpringSource的David Syer跟大家分享了Spring应用的几种事务处理机制、三种XA式、四种非XA式事务协议。读完此文,你可以了解可以用分布

Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式。理想的实现取决于你的应用程序使用何种资源,你愿意在性能、安全、系统稳健性、数据完整方面做出何种权衡。在这次JavaWorld大会上,来自SpringSource的David Syer跟大家分享了Spring应用的几种事务处理机制、三种XA式、四种非XA式事务协议。

Spring框架支持Java Transaction API(JTA),这样应用就可以脱离Java EE容器,转而利用分布式事务以及XA协议。然而即使有这样的支持,XA开销是昂贵的,不稳定而且笨重不利于管理,不过一些其他的应用可以避免使用XA协议。

为了让大家对所涉及的几种分布式事务有所了解,我会分析七种事务处理模式,并 给出具体代码实现。并且从安全或者稳定性入手倒序展示,可以看看从安全、稳定性出发,如何在一般场景下,保障数据高完整性和原子性。当然随着话题的深入, 更多的说明以及限制就会出现。模式也可以从运行时开销倒序展示。考虑到所有模式都是结构化或者学术性的,这一点有别于业务模型,因此我不打算展开业务用例 分析,仅仅关注每种模式其少部分代码如何工作的。

尽管只有起初的三种模式涉及到 XA协议,不过从性能角度出发,这些模式或许无法满足需求。考虑到这些模式无处不在,我不想做过多地扩展,只是对第一种模式做一个简单的展示。读完此文,你可以了解可以用分布式事务做些什么、不能做什么以及如何、何时避免使用XA,何时必须使用。

分布式事务以及原子性

分布式事务涉及不止一个事务资源。比如,在关系数据库和消息中间件之间通信的连接器,通常这些资源拥有类似begin()、rollback()、commit()的API。在此,一个事务资源通常是一个工厂产品,这个工厂通常由底层平台提供:以数据库为例,DataSource提供Connection,或者Java Persistence API(JPA)的EntityManager接口;又如Java Message Service(JMS)提供的Session。

一个典型的例子,一个JMS消息触发一次数据库更新。此过程可以分解成一时间线,一个成功的交互顺序是下面这样:

开启消息事务

接受消息

开启数据库事务

更新数据库

提交数据库事务

提交消息事务

如果数据库出错,比如更新时出现诸如违反约束的问题,一个理想的顺序应该是下面这个样子:

开启消息事务

接受消息

开启数据库事务

更新数据库失败

回滚数据库事务

回滚消息事务

在这个案例中,最后的回滚发生后消息返回给中间件,并且在某种程度返回的消息会被其他事务所接收。通常这是件好事,可能你并没有对失败做记录。自动重试处理异常机制超出了本文的范畴。

以上两种时间线中最重要的特性是它们的原子性,形成一个单一的逻辑事务单元,要么都成功要么都失败。

那么用什么确保时间线会的顺序呢?事务资源之间必须保持某种同步,一旦对某个数据源做提交,要么都提交了,要么都回滚。否者整个事务就不缺乏原子性。之所以是分布式事务,是因为有多个数据源,没有同步就没有原子性。分布式事务技术和概念的核心问题都是围绕资源的同步或者无法同步展开的。

前三种模式的以下讨论都是基于XA协议,考虑到这三种模式分布广泛,本文不会涉及太多的细节,倘若你熟悉XA模式或许愿意直接跳到。

二阶段提交完整XA协议

如果你需要近乎完美的防护 (close-to-bulletproof)确保你的应用事务在断电后恢复以及服务器崩溃,完整XA是不二之选。共享资源通常需要做事务同步,在此情况下,它是一个采用XA协议协调处理过程的信息特殊的事务管理器。在Java领域,从开发者的角度看,这个协议是通过JPA UserTransaction暴露给大家。

基于系统接口,XA作为一种促成科技(enabling technology)对多数开发人员不可见,因此他们需要知道XA在哪、促成什么、耗损如何以及如何利用事务资源。事务管理器采用二阶段提交(2PC)协议,在确保事务结束前所有资源采用同一个事务结果的同时,也会带来性能耗损。

如 果是Spring促成的(Spring-enabled),应用会采用Spring的JtaTransactionManager以及Spring声明式 事务管理,这样会隐藏到了底层事务同步的具体细节。对于开发人员用没用XA的差别就在于对工厂资源的配置:DataSource实例,以及应用的事务管理 器。本文会通过一个应用案例(atomikos-db项目)来揭示这个配置,数据库实例和事务管理器仅是XA或者JTA特定的应用元素。

为了揭示此案例如何工作,在com.springsource.open.db.下运行这个单元测试。一个简单的 MulipleDataSourceTests类仅是将数据插入两个数据源中,并且采用Spring整合支持的特性对事务进行回滚,代码见清单1:

清单1、事务回滚

@Transactional @Test public void testInsertIntoTwoDataSources() throws Exception { int count = getJdbcTemplate().update( "INSERT into T_FOOS (id,name,foo_date) values (?,?,null)", 0, "foo"); assertEquals(1, count); count = getOtherJdbcTemplate() .update( "INSERT into T_AUDITS (id,operation,name,audit_date) values (?,?,?,?)", 0, "INSERT", "foo", new Date()); assertEquals(1, count); // Changes will roll back after this method exits }

接着验证这两个操作是否同时回滚,代码清单如清单2:

清单2、回滚验证

@AfterTransaction public void checkPostConditions() { int count = getJdbcTemplate().queryForInt("select count(*) from T_FOOS"); // This change was rolled back by the test framework assertEquals(0, count); count = getOtherJdbcTemplate().queryForInt("select count(*) from T_AUDITS"); // This rolled back as well because of the XA assertEquals(0, count); }

更进一步理解Spring事务管理如何工作以及如何配置,请参看。

一阶段提交优化XA协议

许多事务管理器采用这种优化模式,可以避免单一事务资源下的2PC过度开销,你的应用服务器最好能够判别此种情况。

协议和最终资源策略

多数XA事务管理器另一个特性是,不论是单一XA兼 容资源还是所有资源都XA兼容,事务管理器均能提供相同的恢复保障。它们是通过给资源排序,并且给非XA资源投票实现,倘若事务提交失败,所有其他的资源 都能回滚。事务有近乎百分百的保障,但缺点是,倘若事务失败,此时不会留下太多信息。换言之,如果要获取这些信息,需要做一些额外的步骤,比如在一些高级实现。

共享事务资源模式
数据统计中,请稍等!
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------