摘要
原子事务处理是在出现故障的情况下,保证一致性的一种广为人知的技术。原子事务处理的ACID属性,可以确保在即便是复杂的业务应用中,不管是否出现并发存取和故障,状态的一致性得以保持。然而,尽管这是一个极其有用的容错技术,但是它对于长时间跨度的事务来说,并不足以满足需要。因为长时间跨度的事务中,对事务属性的放宽是必要的。所谓的扩展事务处理模型已经出现好多年了,但是直到Web服务问世以前,它们仍然趋于停留在学术研究的环境中。在这篇文章中,我们将考察这些需求,并且检验在CORBA的紧耦合环境下开发出的扩展事务处理的业界标准,如何极大地影响了Web服务的松耦合环境。
引言
分布式系统使原先在集中型系统下不常见的可靠性问题突显出来。分布式系统由大量用网络连接起来的计算机所组成,常常会遭受其中的任意子部件出现的故障,比如计算机本身、网络连接、操作系统、或者个别的应用程序,以及一些执行时间不能确定的行为活动等。去中心化允许整个系统的某个部分出现故障,而其他部分保持运行。但这样会导致执行程序过程中出现异常行为的可能。在Web服务出现以后,想利用这个巨大的B2B空间的服务供应商一拥而上。然而,Web是有史以来最大的分布式系统,并且会有故障发生,这些故障会影响在Web 上运行的应用程序的性能和一致性。
原子事务处理是在出现故障的情况下,保证一致性的一种广为人知的技术[1]。它的ACID属性,可以确保在即便是复杂的业务应用中,不管是否出现并发存取和故障,状态的一致性都得以保持。这是一个极其有用的容错技术,尤其在牵扯到多个资源(可能是远程资源)的情况下。
然而,由于 Web服务已经发展成为在跨企业级别集成进程和应用程序的一种方式,传统的事务处理的语义和协议已被证明不合时宜。基于 Web服务的事务与传统事务的不同之处,在于前者的执行周期长,要求事务的提交必须在运行期“协商”,并且隔离级别必须被放宽。所谓的扩展事务处理模型已经出现好多年了,但是直到Web服务问世以前,它们仍然趋于停留在学术研究的环境中。然而,OASIS Web服务事务(WS-TX)技术委员会正在制定用于 Web服务事务管理的标准[2],这个标准就采用了扩展事务处理模型。在这篇文章中,我们将首先考虑为什么传统的原子事务处理不足以满足长周期活动的需要,其次,我们将以 Web服务出现之前在OMG 进行的研究和开发工作为基础,详述 WS-TX 如何解决这些问题。
为什么需要扩展事务处理模型?
许多年以来,分布式对象加上ACID事务为创建高完整性的业务应用程序构建了基础。事务的ACID属性,确保即便在复杂的业务应用程序中,不管是否出现并发存取和故障,应用程序的状态一致性都能得以保持。事务可以由两种方式终止:被提交或者被中止(回滚)。当一个事务被提交时,在其过程中的所有改变将被持久化(被保存在稳定的存储设备上,比如磁盘)。当一个事务被中止时,在事务生命周期中所作的修改都会被撤销。
传统的事务系统使用一种两阶段协议来确保参与者之间的原子性的实现,如图 1:在第一(准备)阶段中,单独的参与者必须使事务的作用域中每一个状态的改变持久化,以便在事务结果一旦得以确定,所作的改变就能被回滚或提交。假定第一阶段没有出现任何故障,则参与者可以在第二(提交)阶段使用在第一阶段持久化的状态“覆盖”原来的状态。
图 1:两阶段提交协议
为了保证一致性,两阶段提交必须是一个阻塞型的协议:在第一阶段的响应返回之后,每一个返回了提交响应的参与者必须保持阻塞状态,直到收到协调程序发出的第二阶段消息。在它们收到消息之前,所有被该参与者使用的资源都无法为其他事务所用,否则会导致非 ACID 行为的产生。如果协调程序在第二阶段消息被发送之前发生故障,这些资源都将保持阻塞状态,直到协调程序完成恢复。
多数人意见组(Consensus groups)
人们很早就意识到,ACID事务本身并不足以用来构造长时间运行的应用程序[3][4]。其中一项著名的改进(由CORBA 对象事务服务 OTS 所支持[5]),就是允许事务的嵌套;此外,嵌套的事务可以是并发的。在这个层次结构中,最外层的事务一般被称为顶级事务。持久性属性只能由顶级事务所拥有,而嵌套事务(子事务)的提交相对于外层事务的提交或者中止来说,是临时的。这样,就考虑到了故障制约策略的具体情况,也就是说,子事务的错误不会一定引起它的外层事务出现错误。在子事务中取得的资源,会在它被提交的时候,被其父事务所继承(保留),而且只在顶级事务完成时才能被释放(假设没有故障发生)。换句话说,这些资源会被保持到顶级事务结束为止。
上述的改进,在应用程序功能可以被表示为单独的顶级事务的时候是可以满足需求的。但事实上常常并不是这么一回事。顶级事务最适合被视为“短寿命”实体,对系统进行稳定的状态变更[4];它们比较不适合用于构造“长寿命”的应用程序功能(例如运行数个小时乃至数天)。长跨度的顶级事务可能会因为长时间占用某些资源,而使系统的并发性降低到令人无法接受的程度;此外,如果这样一个事务中止的话,许多之前完成的有价值的工作可以被撤销。简而言之,如果应用程序由一系列的事务所组成,那么在运行期间,代表运行中的应用程序的整个活动,会被频繁地要求放宽对于各个事务的其中一些 ACID属性的要求。于是,整个活动可以被看成一个非 ACID的“扩展事务处理”。
控制模型的范围[6]描述了扩展事务处理中的恢复和提交等根本概念。在开发具体的扩展事务处理模型方面,人们已经进行了许多的研究[例如 7 - 10],集中在多数人意见组的意见上。并非在某个特订的扩展事务处理中的所有参与者都必须得到相同的结果;一个特定的事务可能会拥有多个不同的多数人意见组,其中每个组中的参与者得到不同的结果。另外,在某一些多数人意见组中可能允许放宽某个特定事务的原子性的限制,从而允许参与者的子集得到不同的结果。这种在一个组中的参与者列表的灵活性,是这些类型的扩展事务处理和传统的事务系统的一个重要区别。
进而言之,假如需要的话,参与者应当可以退出一个多数人意见组。参与者可能不再希望参与多数人意见组的理由会有很多:例如,它所完成的工作可以安全结束,而不必考虑多数人意见组的最终结果;或者,在多数人意见组取消工作的时候,另外一个独立任务(不同的服务或者领域)可能有必要执行反效果。
多数人意见组在参与者当中取得了一致性结果,但他们仅仅是冰山一角。在业务对业务(business-to-business)关系中,常常存在着这些组的层次关系(工作的范围),在这些层次关系之间包含着父子关系。总的来说,在业务事务处理内部确认或者取消已经完成的工作,将意味着由参与者来进行决策。譬如,应用程序可能选择执行变更,作为临时效果,并且使它们对其他业务事务处理可见。同时,应用程序可能储存必要的临时信息,用于撤销这些变更。在确认时,它只要把这些撤销信息丢弃就可以了;或者,在取消时,它可以应用这些撤销的改变。例如,应用程序可以采取类似这样基于补偿的方案,也可以采用传统的“回滚”方法。
除了理解这些结果以外,业务事务处理内部的参与者可能需要在事务处理的过程中支持临时或者尝试性的状态变更。这些参与方(parties)也必须通过确认(最终效果)或者取消(反效果)来支持业务事务处理的完成。总的来说,在业务事务处理内部确认或者取消已经完成的工作,将意味着由参与者来进行决策。譬如,应用程序可能选择执行变更,作为临时效果,并且使它们对其他业务事务处理可见。同时,应用程序可能储存必要的临时信息,用于撤销这些变更。在确认时,它只要把这些撤销信息丢弃就可以了;或者,在取消时,它可以应用这些撤销的改变。例如,应用程序可以采取类似这样基于补偿的方案,也可以采用传统的“回滚”方法。