事務服務淺析

 事務是一個非常重要的編程概念,使用事務,可以很簡單地構造出可靠穩定的應用程序,本文以許多具體的例子介紹了事務服務的概念和事務服務的具體實現。
  本文共分兩部分:第一部分從事務服務整體描述的角度簡要介紹了事務服務產生的動機、事務服務的應用和事務服務的功能,其中以具體的例子解釋了相關概念和事務服務涉及到的一些術語;第二部分以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映射。這個接口由事務管理器和資源管理器來使用,對於應用程序和應用服務器而言這個接口是不可見的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章