事務小結

事務

1.XA(有一個單點協調事務管理器)

 

XA是由X/Open組織提出的分佈式事務的規範。XA規範主要定義了(全局)事務管理器(Transaction Manager)和(局部)資源管理器(Resource Manager)之間的接口。XA接口是雙向的系統接口,在事務管理器(Transaction Manager)以及一個或多個資源管理器(Resource Manager)之間形成通信橋樑。XA之所以需要引入事務管理器是因爲,在分佈式系統中,從理論上講(參考Fischer等的論文),兩臺機器理論上無法達到一致的狀態,需要引入一個單點進行協調。事務管理器控制着全局事務,管理事務生命週期,並協調資源。資源管理器負責控制和管理實際資源(如數據庫或JMS隊列)。下圖說明了事務管理器、資源管理器,與應用程序之間的關係:

2.JTA
作爲java平臺上事務規範JTA(Java Transaction API)也定義了對XA事務的支持,實際上,JTA是基於XA架構上建模的,在JTA 中,事務管理器抽象爲javax.transaction.TransactionManager接口,並通過底層事務服務(即JTS)實現。像很多其他的java規範一樣,JTA僅僅定義了接口,具體的實現則是由供應商(如J2EE廠商)負責提供,目前JTA的實現主要由以下幾種:
1.J2EE容器所提供的JTA實現(JBoss)
2.獨立的JTA實現:如JOTM,Atomikos.這些實現可以應用在那些不使用J2EE應用服務器的環境裏用以提供分佈事事務保證。如Tomcat,Jetty以及普通的java應用。

 

1.         兩階段提交(分佈式事務)

所謂的兩個階段是指:第一階段:準備階段和第二階段:提交階段。

階段1:請求階段(commit-request phase,或稱表決階段,voting phase

在請求階段,協調者將通知事務參與者準備提交或取消事務,然後進入表決過程。在表決過程中,參與者將告知協調者自己的決策:同意(事務參與者本地作業執行成功)      或取消(本地作業執行故障)。

事務協調者(事務管理器)給每個參與者(資源管理器)發送Prepare消息,每個參與者要麼直接返回失敗(如權限驗證失敗),要麼在本地執行事務,寫本地的redoundo日誌,但不提交,到達一種萬事俱備,只欠東風的狀態。(關於每一個參與者在準備階段具體做了什麼目前我還沒有參考到確切的資料,但是有一點非常確定:參與者在準備階段完成了幾乎所有正式提交的動作,有的材料上說是進行了試探性的提交,只保留了最後一步耗時非常短暫的正式提交操作給第二階段執行。)

階段2:提交階段(commit phase

在該階段,協調者將基於第一個階段的投票結果進行決策:提交或取消。當且僅當所有的參與者同意提交事務協調者才通知所有的參與者提交事務,否則協調者將通知所有     的參與者取消事務。參與者在接收到協調者發來的消息後將執行響應的操作。

注意兩階段提交協議與兩階段鎖協議不同,兩階段鎖協議爲一致性控制協議。

如果協調者收到了參與者的失敗消息或者超時,直接給每個參與者發送回滾(Rollback)消息;否則,發送提交(Commit)消息;參與者根據協調者的指令執行提交或者回滾操作,釋放所有事務處理過程中使用的鎖資源。(注意:必須在最後階段釋放鎖資源)
將提交分成兩階段進行的目的很明確,就是儘可能晚地提交事務,讓事務在提交前儘可能地完成所有能完成的工作,這樣,最後的提交階段將是一個耗時極短的微小操作,這種操作在一個分佈式系統中失敗的概率是非常小的,也就是所謂的網絡通訊危險期非常的短暫,這是兩階段提交確保分佈式事務原子性的關鍵所在。(唯一理論上兩階段提交出現問題的情況是當協調者發出提交指令後當機並出現磁盤故障等永久性錯誤,導致事務不可追蹤和恢復)

缺點:

從兩階段提交的工作方式來看,很顯然,在提交事務的過程中需要在多個節點之間進行協調,而各節點對鎖資源的釋放必須等到事務最終提交時,這樣,比起一階段提交,兩階段提交在執行同樣的事務時會消耗更多時間。事務執行時間的延長意味着鎖資源發生衝突的概率增加,當事務的併發量達到一定數量的時候,就會出現大量事務積壓甚至出現死鎖,系統性能就會嚴重下滑。這就是使用XA事務

2.     一階段提交(Best Efforts1PC模式)

一階段提交非常直白,就是從應用程序向數據庫發出提交請求到數據庫完成提交或回滾之後將結果返回給應用程序的過程。

3.      事務補償機制

事務鏈中每一個正向事務操作對應一個逆向事務操作,完整事務鏈條必須可逆業務操作。
在這種情況下以上面例子來說,首先調用取款服務,完全調用成功並返回,數據已經持久化。然後調用異地的存款服務,如果也調用成功,則本身無任何問題。如果調用失敗,則需要調用本地註冊的逆向服務(本地存款服務),如果本地存款服務調用失敗,則必須考慮重試,如果約定重試次數仍然不成功,則必須log到完整的不一致信息。也可以是將本地存款服務作爲消息發送到消息中間件,由消息中間件接管後續操作。 

在上面方式中可以看到需要手工編寫大量的代碼來處理以保證事務的完整性,我們可以考慮實現一個通用的事務管理器,實現事務鏈和事務上下文的管理。對於事務鏈上的任何一個服務正向和逆向操作均在事務管理和協同器上註冊,由事務管理器接管所有的事務補償和回滾操作。

冪等操作:

重複調用多次產生的業務結果與調用一次產生的業務結果相同,簡單點講所有提供的業務服務,不管是正向還是逆向的業務服務,都必須要支持重試。因爲服務調用失敗這種異常必須考慮到,不能因爲服務的多次調用而導致業務數據的累計增加或減少。

基於消息的最終一致性 

對於轉賬操作,原有的兩個服務調用變化爲第一步調用本地的取款服務,第二步發送異地存款的異步消息到消息中間件。如果第二步在本地,則保證事務的完整性基本無任何問題,即本身就是本地事務的管理機制。只要兩個操作都成功即可以返回客戶成功。 

其次對於前面討論,如果真正需要的是實時的一致性,那麼即使採用事務補償機制,也無法達到實時的一致性。即很可能在兩個業務服務調用中間,客戶前臺業務操作對持久化的數據進行了其它額外的操作。在這種模式下,我們不得不考慮需要在數據庫表增加業務狀態鎖的問題,即整個事務沒有完整提交併成功前,第一個業務服務調用雖然持久化在數據庫,但是仍然是一箇中間狀態,需要通過業務鎖來標記,控制相關的業務操作和行爲。但是在這種模式下無疑增加了整個分佈式業務系統的複雜度。 

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