1、事務的概念算法
事務是一組操做的執行單元,相對於數據庫操做來說,事務管理的是一組SQL指令,好比增長,修改,刪除等,事務的一致性,要求,這個事務內的操做必須所有執行成功,若是在此過程種出現了差錯,好比有一條SQL語句沒有執行成功,那麼這一組操做都將所有回滾數據庫
最經典的例子即是:A向B匯款500元,B帳戶多了500元,這整個過程,要麼所有正常執行,要麼所有回滾,否則就會出現A扣款,B收不到錢,或者A沒扣款,B收到500元的狀況,這種場景是災難性的。編程
事務特性(ACID)
(1)Atomic(原子性):要麼都成功,要麼都失敗
(2)Consistent(一致性):數據應該不被破壞
(3)Isolate(隔離性):用戶間操做不相混淆
(4)Durable(持久性):永久保存 服務器
2、本地事務和分佈式事務網絡
本地事務:本地事務是在同一個JVM實例中調用不一樣的資源造成事務,緊密依賴於底層資源管理器(例如數據庫鏈接 ),事務處理侷限在當前事務資源內。此種事務處理方式不存在對其餘應用服務器或實例的依賴。分佈式
如上述說到的匯款案例來講,若兩個過程都在同一個JVM實例中,使用同個數據庫鏈接,則事務比較好控制,以下圖:函數
分佈式事務:分佈式事務是在一個JVM實例中調用不一樣的服務造成事務,不一樣的服務可能不在同一個JVM實例中,可能涉及到操做多個數據庫的事務,必須保證每一個獨立節點上的數據操做能夠知足ACID。spa
如上述說到的匯款案例來講,若兩個過程在不一樣的JVM實例中,使用不一樣的數據庫鏈接,則事務很差控制,緣由是A,B沒法知道事務在其餘地方所作的全部動做,沒法實現事務的一致性,以下圖,A,B各自使用本身的事務管理完成begin,commit,rollback等操做,AB整個過程是沒法實現事務一致性的。日誌
3、對分佈式事務的處理中間件
在分佈式系統中,各個節點之間在物理上相互獨立,經過網絡進行溝通和協調。可是相互獨立的節點沒法知道其餘節點的事務執行狀況,要保證全部節點上的寫操做,要麼所有提交,要麼所有rollback,最好的辦法就是引入coordinator,即協調者來協調和通知各個節點上的事務執行狀況。
Java 事務編程接口(JTA:Java Transaction API)和 Java 事務服務 (JTS:Java Transaction Service) 爲 J2EE 平臺提供了分佈式事務服務。分佈式事務(Distributed Transaction)包括事務管理器(Transaction Manager)和一個或多個支持 XA 協議的資源管理器 ( Resource Manager )。咱們能夠將資源管理器看作任意類型的持久化數據存儲;事務管理器承擔着全部事務參與單元的協調與控制。
因爲事務管理器統一管理全部事務參與單元,則全部事務參與單元都應實現同一套協議,才方便事務管理器的管理,就好似一個老師A管理一班學生,全部學生按照老師約定好的形式完成做業,以後交由同一個老師批改,批改後統一退回。若同一個做業,部分學生按照A老師的標準完成,部分同窗按照B老師的標準完成,再提交上去批改,則最終獲得的結果就可能互相不一致了。
4、XA協議
分佈式事務中,全部的事務單元都須要實現統一的協議,XA 就是定義的交易中間件與數據庫之間的接口規範(即接口函數),交易中間件用它來通知數據庫事務的開始、結束以及提交、回滾等。 XA 接口函數由數據庫廠商,或消息中間件廠商提供。
以下圖,咱們能夠將 JTA 的事務管理器和資源管理器理解爲兩個方面:面向開發人員的使用接口(事務管理器)和麪向服務提供商的實現接口(資源管理器),開發人員使用開發人員接口,實現應用程序對全局事務的支持;各提供商(數據庫,消息中間件等)依據提供商接口(即XA接口)的規範提供事務資源管理功能;事務管理器( Transaction Manager )將應用對分佈式事務的使用映射到實際的事務資源並在事務資源間進行協調與控制,使得 JTA 能夠在異構事務資源之間執行協同溝通。
5、強一致性事務實現原理
2PC,即二階段提交,是分佈式事務中一個很重要的協議,當一個事務跨越多個節點時,爲了保持事務的ACID特性,須要引入一個coordinator,即協調者做爲的組件來統一掌控全部節點(稱做參與者)的操做結果並最終指示這些節點是否要把操做結果進行真正的提交或回滾。
二階段提交的算法思路能夠歸納爲: 參與者將操做成敗通知協調者,再由協調者根據全部參與者的反饋情報決定各參與者是否要提交操做仍是回滾操做。
各參與者成功提交事務流程:
(1)在一個有A,B,C參與的事務中,引入一個協調者,用來協調和通知各參與者執行相應的事務動做,其中黑線爲協調者發起的指令,紅線爲參與者響應的指令。
(2)協調者通知全部參與者節點準備提交事務,參與者節點執行事務操做,並將Undo信息和Redo信息寫入日誌,但此時不提交事務。
(3)協調者收到各參與者準備提交完成的指令,沒有任何節點出錯,此時通知全部節點提交事務。
(4)參與者節點正式完成提交操做,並釋放在整個事務期間內佔用的資源。
(5)協調者收到全部參與者確認提交完畢的答覆,此時整個事務完成。
各參與者提交事務失敗流程:
(1)在一個有A,B,C參與的事務中,引入一個協調者,用來協調和通知各參與者執行相應的事務動做,其中黑線爲協調者發起的指令,紅線爲參與者響應的指令。
(2)協調者通知全部參與者節點準備提交事務,參與者節點執行事務操做,並將Undo信息和Redo信息寫入日誌,但此時不提交事務,但此時B節點在準備執行操做事務時出現了異常,則返回給協調者準備失敗的響應信息
(3)協調者雖然收到A跟C準備完成的響應,但B返回的狀態是準備失敗,此時進入通知全部參與者回滾的階段
(4)參與者節點正式完成回滾操做,並釋放在整個事務期間內佔用的資源。
(5)協調者收到全部參與者確認回滾完畢的答覆,此時整個事務完成
結論:無論最後結果如何,第二階段都會結束當前事務。
建議:少使用分佈式事務,在分佈式事務這個問題上,還不多有成熟牛逼的產品,並且分佈式事務過程當中,涉及到了各個節點的通知,二次通知,當節點多的時候,協調者的壓力巨大,並且整個流程對業務的時間開銷是巨大的,因此建議謹慎使用分佈式事務,即便二階段看似能處理好分佈式節點的ACID問題,可是其自己也存在不小的問題。
一、同步阻塞問題。執行過程當中,全部參與節點都是事務阻塞型的。當參與者佔有公共資源時,其餘第三方節點訪問公共資源不得不處於阻塞狀態。
二、單點故障。因爲協調者的重要性,一旦協調者發生故障。參與者會一直阻塞下去。尤爲在第二階段,協調者發生故障,那麼全部的參與者還都處於鎖定事務資源的狀態中,而沒法繼續完成事務操做。(若是是協調者掛掉,能夠從新選舉一個協調者,可是沒法解決由於協調者宕機致使的參與者處於阻塞狀態的問題)
三、數據不一致。在二階段提交的階段二中,當協調者向參與者發送commit請求以後,發生了局部網絡異常或者在發送commit請求過程當中協調者發生了故障,這回致使只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求以後就會執行commit操做。可是其餘部分未接到commit請求的機器則沒法執行事務提交。因而整個分佈式系統便出現了數據部一致性的現象。
四、二階段沒法解決的問題:協調者再發出commit消息以後宕機,而惟一接收到這條消息的參與者同時也宕機了。那麼即便協調者經過選舉協議產生了新的協調者,這條事務的狀態也是不肯定的,沒人知道事務是否被已經提交。
注:二階段提交的缺點描述引用來自http://blog.jobbole.com/95632/。