事务服务浅析

  事务是一个非常重要的编程概念,使用事务,可以很简单地构造出可靠稳定的应用程序,本文以许多具体的例子介绍了事务服务的概念和事务服务的具体实现。
  本文共分两部分:第一部分从事务服务整体描述的角度简要介绍了事务服务产生的动机、事务服务的应用和事务服务的功能,其中以具体的例子解释了相关概念和事务服务涉及到的一些术语;第二部分以J2EE中的事务服务为例对事务的实现作简要的介绍。

第I部分 事务服务简述
 

1. 事务综述
 

事务是一个非常重要的编程概念,使用事务,可以很简单地构造出可靠稳定的应用程序,尤其对那些需要进行并发数据访问的应用程序,事务更是重要的多。事务的概念最初应用在那些用于商务操作的应用程序上,在这些应用中,事务用来保护中央数据库中的数据。随后,随着分布式计算的发展,事务在分布式计算领域中也得到了广泛的应用。现在,在分布式计算领域中,公认为事务是构造可靠性分布式应用程序的关键。

1.1事务产生的动机

1.1.1原子操作

考虑这样一个应用:用户把钱从一个银行账号转账至另一个银行账号,需要将资金从一个银行账号中取出,然后再存入另一个银行账号中。理想来说,这两次操作都应该成功。但是,如果有错误发生,则两次操作都应该失败,否则的话,操作之后其中一个账号中的金额将会是错误的,整个操作过程应该是原子性的,两个操作都是一个原子事务操作的一部分。

可以使用异常处理来处理上述问题,代码如下:


try{
  //从账户1中取款
}
catch(Exception e){
	//如果发生错误,则终止操作
	return;
}
try {
	//如果第一步没有发生错误,则将提取出的资金存入账户2	
}
catch(Exception e) {
//如果发生错误,则终止这步操作,并且将从账户1中取出的资金再重新存回到账户1中
return ;
}

上面这种解决方法从存在着下面的问题:

  • 程序拖沓冗长
  • 必须考虑到每一步中可能发生的每一个问题,并且要编写错误处理程序来考虑如何撤销所作的操作
  • 如果执行的是比简单的取款、存款操作要复杂的多的程序,那么错误处理程序将会变得难以控制。
  • 编写测试程序将会非常困难

因此,需要一种事务处理机制来保证这种原子性的操作。

1.1.2 网络故障或机器故障

为了在发生严重故障之后,能够保证系统的状态是一致的,所以需要一种恢复性的机制来保证这一点。

1.1.3 数据共享

需要一种机制来保证多用户并发访问数据的问题。

以上这些问题的解决方法,便是使用事务服务。

1.2 使用事务服务带来的好处

使用事务,便可以利用事务的四个重要属性:ACID。

  • 原子性( atomic):事务中包含的各项操作必须全部成功执行或者全部不执行。任何一项操作失败,将导致整个事务失败,其他已经执行的任务所作的数据操作都将被撤销,只有所有的操作全部成功,整个事务才算是成功完成。
  • 一致性( consistent):保证了当事务结束后,系统状态是一致的。那么什么是一致的系统状态?例如,如果银行始终遵循着"银行账号必须保持正态平衡"的原则,那么银行系统的状态就是一致的。上面的转账例子中,在取钱的过程中,账户会出现负态平衡,在事务结束之后,系统又回到一致的状态。这样,系统的状态对于客户来说,始终是一致的。
  • 隔离性( isolated):使得并发执行的事务,彼此无法看到对方的中间状态。保证了并发执行的事务顺序执行,而不会导致系统状态不一致。
  • 持久性( durable):保证了事务完成后所作的改动都会被持久化,即使是发生灾难性的失败。可恢复性资源保存了一份事务日志,如果资源发生故障,可以通过日志来将数据重建起来。

2. 事务应用
 

事务服务支持的应用由下列实体组成:

  • 事务客户(TC,Transactional Client)
  • 事务对象(TO,Transactional Objects)
  • 可恢复对象(Recoverable Objects)
  • 提供事务支持的服务器(Transactional Servers)
  • 可恢复资源服务器(Recoverable Servers)

下图展示了一个简单的事务应用,包含了基本的事务元素:


  • 事务客户:事务客户是一个独立的程序,调用参与事务的多个事务对象。发起事务的程序被称为事务发起者(Transaction Originator)。
  • 事务对象:指那些在事务范围内行为会被影响的对象。事务对象自身包含了对持久化数据的操作或者通过事务请求间接对持久化数据进行操作。事务服务并不要求所有的事务请求都具有事务性的行为。与事务对象相对的是非事务对象。
  • 可恢复对象(Recoverable Objects)和资源对象(Resource Objects):如果事务提交和事务的回滚将影响某个对象里面的数据,那么这个对象称为一个可恢复对象。一个对象可以是事务对象而不是可恢复对象,因为事务对象可以使用其他的可恢复对象。可恢复对象必须将自己注册为事务服务中的一个资源对象,才可以参与到事务中。
  • 支持事务的服务器:例如应用服务器
  • 可恢复服务器:例如数据库

3. 事务服务提供的功能
 

事务服务提供下列操作:

  • 控制事务的范围和持续时间
  • 让多个对象参与到一个单独的原子性事务中
  • 将对象内部状态的改变同事务相联系
  • 协调事务完成

3.1事务模型

  • 平面型事务模型整个事务是一个整体,不可划分为子事务。
  • 嵌套式事务模型嵌套有子事务,子事务中还可以嵌套有子事务,整个是一个树形结构。旅行计划问题:
    • 购买从美国波士顿到美国纽约的火车票
    • 购买从美国纽约到英国伦敦的飞机票
    • 购买从英国伦敦到法国巴黎的气艇票
    • 发现没有飞往法国巴黎的气艇票
    这对于平面型事务来说,只能有一个选择:事务失败。这样由于没有飞往巴黎的气艇票,将会取消所有的出行计划。但是在这里,完全可以采用其他的旅行方式(购买火车票或者飞机票)来代替气艇。因此需要一个更加健壮的事务模型来解决这个问题。可以将整个事务划分为若干个子事务,整个事务可以重新执行单个子事务来尝试完成事务,如果最终某个单个子事务无法完成,则整个事务失败。
  • 其他事务模型
    锁链式模型、传奇式模型等。

3.2 事务的终止

通过发出提交请求或回滚请求来终止事务。通常,事务是由发起事务的客户(事务发起者)来终止的。

3.3事务的完整性

某些事务服务的实现为了保证事务的完整性,在事务服务接口的使用上施加了一些限制。这称为checked事务行为。例如,在事务的所有任务完成之前提交事务会导致数据不完整。事务服务的Checked实现会阻止事务的过早提交。其他事务服务的实现则完全依赖应用程序来提供事务的完整性保证,这称为unchecked事务行为。

3.4事务的上下文

事务上下文惟一标识了一个事务,保存了事务的当前状态。通过查询事务上下文,可以得知自身是否处于事务中,所在事务的状态以及其他一些有用的信息。

事务上下文可以作为事务操作调用的一部分隐式地传递给事务对象。事务服务也允许程序员将事务上下文作为事务请求的显示参数来传递。

4. 分布式事务
 

分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。为了实现分布式事务,需要使用下面将介绍的两阶段提交协议。

  • 阶段一:开始向事务涉及到的全部资源发送提交前信息。此时,事务涉及到的资源还有最后一次机会来异常结束事务。如果任意一个资源决定异常结束事务,则整个事务取消,不会进行资源的更新。否则,事务将正常执行,除非发生灾难性的失败。为了防止会发生灾难性的失败,所有资源的更新都会写入到日志中。这些日志是永久性的,因此,这些日志会幸免遇难并且在失败之后可以重新对所有资源进行更新。
  • 阶段二:只在阶段一没有异常结束的时候才会发生。此时,所有能被定位和单独控制的资源管理器都将开始执行真正的数据更新。

在分布式事务两阶段提交协议中,有一个主事务管理器负责充当分布式事务协调器的角色。事务协调器负责整个事务并使之与网络中的其他事务管理器协同工作。


为了实现分布式事务,必须使用一种协议在分布式事务的各个参与者之间传递事务上下文信息,IIOP便是这种协议。这就要求不同开发商开发的事务参与者必须支持一种标准协议,才能实现分布式的事务。

以上从事务整体描述的角度简要介绍了事务服务产生的动机、事务服务的应用和事务服务的功能,下面以J2EE中的事务服务为例对事务的实现作简要的介绍。

 

第II部分 J2EE中的事务服务
 

简介
 

Java TM2 Platform, Enterprise Edition(J2EE)简化了分布式事务管理应用程序的编写。J2EE包括了两套规范,用来支持分布式的事务,一种是Java Transaction API(JTA),另一种是Java Transaction Service(JTS)。JTA是一种高层的,与实现无关的,与协议无关的API,应用程序和应用服务器可以使用JTA来访问事务。JTS则规定了支持JTA的事务管理器的实现规范,在高层API之下实现了OMG Object Transaction Service(OTS) 1.1规范的Java映射。JTS使用Internet Inter-ORB Protocol(IIOP)来传播事务。作为J2EE平台实现的一部分,SUN实现了一个支持JTS的事务管理器,同时还实现了JTA。

JTA和JTS让J2EE应用服务器完成事务管理,这样就使得组件开发人员摆脱了事务管理的负担。开发者只需在部署描述符中声明事务管理属性,便可以使得EJB组件参与到事务之中,由应用服务器来负责事务的管理。

  • JTS规范定义了事务管理器的实现。JTS规范中定义的事务管理器在高层支持JTA接口规范,在底层则实现了OTS1.1(CORBA Object Transaction Service)的标准Java映射。OMG使用IDL(接口定义语言)定义了事务服务语言中性的实现,JTS则对这个IDL的事务服务实现作了标准的Java映射。JTS使用OTS接口实现了互操作和移植性。OTS接口定义了一组标准的机制,使得JTS事务管理器之间可以使用IIOP(Internet InterORB协议)来生成并传播事务上下文。
  • 从事务管理器的角度出发,事务服务的具体实现是不需要暴露出来的,只需要定义高层接口,使得事务服务的用户可以驱动事务界限、资源获取、事务同步和事务恢复过程。JTA的目的是定义事务管理器所要求的本地Java接口,从而在企业级分布计算环境中支持事务管理。下图中的小半圆代表JTA规范。


J2EE事务服务的层次关系
 

企业级Java中间件的分布式事务服务包括五层:事务管理器(Transaction Manager)、应用服务器(Application Server)、资源管理器(Resource Manager)、应用程序(Application Program)和通信资源管理器(Communication Resource Manager)。每一层都通过实现一组事务API和相关机制参与到分布式事务处理系统中。

  • 事务管理器:是一个系统级的组件,是事务服务的访问点。提供了一组服务和相关的管理机制,用于支持事务划分、事务资源管理、事务同步和事务上下文的传播。
  • 应用服务器(或者称为TP monitor)提供了支持应用程序运行环境的基础设施,这个运行环境包括了事务状态管理。应用服务器的一个例子是EJB服务器。
  • 资源管理器(通过资源适配器[Resource Adapter],资源适配器类似于数据库连接)为应用程序提供了对资源的访问。资源管理器通过实现一组事务资源接口来参与到分布式事务中。事务管理器使用这组事务资源接口在处理事务联系、事务完成和事务恢复的相关工作。资源管理器的一个例子是关系数据库服务器。
  • 基于组件的事务性应用运行在应用服务器环境中,需要依赖应用服务器通过事务属性声明设置所提供的事务管理支持。这种类型应用的典型例子是EJB。除此之外,一些独立的Java客户端程序需要使用应用服务器或事务管理器所提供的高层接口来控制事务界限。
  • 通讯资源管理器(CRM)支持事务上下文的传播和事务服务的访问请求。JTA文档中没有规定通信的要求。请参考JTS规范[2]获得有关事务管理器之间互操作的详细信息。

从事务管理器的角度出发,事务服务的具体实现是不需要暴露出来的,只需要定义高层接口,使得事务服务的用户可以驱动事务界限、资源获取、事务同步和事务恢复过程。JTA的目的是定义事务管理器所要求的本地Java接口,从而在企业级分布计算环境中支持事务管理。下图中的小半圆代表JTA规范。


JTS中规定的事务管理器的实现
 

本节从事务管理器实现者的角度描述了实现方面的要求。如下图,事务管理器必须实现JTA接口,用于支持应用服务器和资源管理器。不要求实现对JDBC 1.0 Driver和非JTA资源管理器支持。也不要求实现对各种CORBA应用实体的支持,如事务客户端(Transactional Client)、事务服务器(Transactional Server)和恢复服务器(Recoverable Server)。


Java Transaction API
 

Java Transaction API由三部分组成:高层的应用事务划分接口(供事务客户使用)、高层的事务管理器接口(供应用服务器使用)和X/Open XA协议的标准Java映射(供事务性资源管理器使用)。

4.1 UserTransaction接口

Javax.transaction.UserTransaction接口使得应用程序能够编程控制事务边界。这个接口可以由Java客户端程序或者EJB来使用。

4.1.1在EJB Server中的UserTransaction支持

EJB中对事务的管理有两种类型:

  1. Bean自管理事务对于自管理事务的EJB,需要从EJB上下文中获取UserTransaction的接口引用,由自己负责完成事务的开始、提交或者回滚。
    
    try 
    {
    javax.transaction.UserTransaction userTran = ctx.getUserTransaction();
    userTran.begin();
    … //执行事务性的程序逻辑
    userTran.commit();
    }
    catch(Exception e) 
    {
    	userTran.rollBack();
    	throw new Exception("……");
    }
    
    EJB这样处理事务称为编程型事务。
  2. 由容器负责事务管理对于这样的EJB,只需在其部署描述符中指定所需的事务相关属性,便可由EJB容器代替EJB进行事务管理。这称为声明式事务。

4.1.2 事务客户端中的UserTransaction支持

Java客户端程序需要首先通过JNDI来获得UserTransaction对象的引用,然后使用该对象的方法完成事务的开始、提交或者回滚。


java.util.Properties env = …
Context ctx = new InitialContext(env);
Javax.transaction.UserTransaction userTran = 
(javax.transaction.UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
userTran.commit()
try 
{
	userTran.commit();
}
catch(Exception e) 
{
	userTran.rollBack();
	throw new Exception("……");
}

4.2 TransactionManager接口

应用服务器使用javax.transaction.TransactionManager接口来代表受控的应用程序控制事务的边界。例如,EJB容器为事务性EJB组件管理事务状态。

4.3 Transaction接口

使用Transaction接口可以执行与目标对象相关联的事务操作。

4.4 XAResource接口

Javax.transaction.xa.XAResource接口是基于X/Open CAE规范(分布式事务处理:XA规范)工业标准XA接口的Java映射。 XAResource接口定义了分布式事务处理环境(DTP)中资源管理器和事务管理器之间是如何交互的。资源管理器的资源适配器实现了XAResource接口,将事务同事务资源联系起来,类似关系数据库的一个连接。


4.5 Xid接口

Javax.transaction.xa.Xid接口是X/Open事务标识符XID结构的Java映射。这个接口由事务管理器和资源管理器来使用,对于应用程序和应用服务器而言这个接口是不可见的。

文章引自: 事务服务浅析(IBM)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值