維護系統一致性和正確地處理錯誤恢復挑戰的最佳方式是使用事務。數據庫
一個事務就是一個複雜操做的集合,這個集合中任何一個操做的失敗都會引發整個集合的失敗。編程
儘管在事務進行時系統被容許暫時出於不一致的狀態,可是一旦事務結束,系統必定會處於一直的狀態。分佈式
事務資源
事務編程須要資源(如數據庫或消息隊列)一塊兒協做,這類資源要可以參與事務並回滾在事務中發生的變化。優化
通常狀況下,咱們必須通知這些但願執行事務性工做的資源,這個行爲稱爲在事務中登記資源。一些資源支持自動登記,也就是說它們可以檢測到自身是否被事務訪問,並完成登記。資源呢一旦被登記,咱們就可以對它執行操做。若是沒有錯誤發生,要求提交資源的全部狀態發生改變;剮有錯誤發生,要求回滾資源的狀態的全部變化。spa
在一個事務處理中,不要訪問非事務的資源很關鍵(如文件系統),由於事務一旦被停止,是不會回滾這些非事務資源上的改變。code
事務屬性
當在面向服務的應用程序中使用事務時,必須遵照四個核心屬性,也就是ACID:原子性(Atomic)、一致性(Consistent)、隔離性(Isolated)和持久性(Durable)。blog
原子性
爲了是事務具備原子性,當一個事務結束時,必須把對資源狀態已經作的全部改變視爲一個原子的,不可分割的操做。隊列
當事務結束時,事務是不允許遺留任何工做在後臺處理,由於這些操做違反了原子性。全部事務產生的操做必須包含在事務中。事務
事務做爲一個總體,要麼成功,要麼失敗。資源
一致性
一致性意味着事務必須是系統處於一個一致的狀態。一致性和原子性不一樣。即便狀態的全部改變被做爲一個原子操做提交了,事務也必須保證全部的改變都是一致的。
事務必須作到的就是讓系統從一個一致的狀態轉移到另外一個一致的狀態。
隔離性
隔離性意味着沒有其它的實體在事務過程當中可以看到資源的狀態,由於中間狀態極可能是不一致的。即便中間狀態是一致的,事務依然可以停止,全部的改變也能夠被回滾。
參與事務的資源必須對事務所訪問的數據枷鎖,以防止任何其它代碼的訪問,同時必須在事務提交或停止取消對數據的所保護,以便其它代碼能夠訪問。
持久性
持久性的意思是一旦成功提交,基於持久化資源(好比數據庫)的數據將會被持久化,對數據的改變是永久性的。
WCF服務可以直接處理事務性的資源,並經過顯式地使用編程模型(如ADO.NET)來管理事務。以下,使用這個模型,能夠顯式地啓動和管理事務。
[ServiceContract] interface IMyContract { [OperationContract] void MyMethod(); } class MyService : IMyContract { public void MyMethod() { string connectionString = "...."; using (IDbConnection connection=new SqlConnection(connectionString)) { connection.Open(); using (IDbCommand command=new SqlCommand()) { command.Connection = connection; using (IDbTransaction transaction =connection.BeginTransaction()) { command.Transaction = transaction; try { //這裏操做數據庫 transaction.Commit(); //提交事務 } catch (Exception) { transaction.Rollback(); //回滾事務 throw; } } } } } }事務性管理的挑戰
雖然編程模型十分簡單,不須要服務執行任何事務,可是這個最適合單個客戶端調用單個數據庫,服務會啓動並管理事務,以下所示:
可是,一個面向服務的應用系統,客戶端一次於多個服務交互,而且涉及到多個資源,以下圖所示
如今問題是,哪個參與的服務負責發起事務並管理資源?若是你們都服務的話,就會以多個事務結束;若是服務裏包含過多的業務邏輯將會引發服務、資源之間緊密耦合的問題;再說哪一個服務服負責提交或回滾事務呢;這個服務如何直到其它事務的 狀況呢……
一種可行的方法是,經過爲事務協調增長代碼能夠把客戶端與服務結合起來,可是這個比較脆弱,業務流程或服務數量變化都會致使這個方法失效。
剛纔介紹的事務類型 稱爲分佈式事務。一個分佈式事務包含兩個或多個獨立的服務(一般在不一樣的執行上下文裏),或者一個服務包含多個事務資源。對於一個分佈式事務,須要依賴兩階段提交協議和一個事務管理器。事務管理器是管理事務的第三方,由它來負責客戶端和服務端兩階段提交協議。
爲了克服分佈式事務的複雜性,事務管理器使用一個稱做兩階段提交協議的事務管理協議來決定事務提交或回滾。兩階段提交協議在分佈式事務中強調原子性與一致性。讓WCF支持多客戶端、服務以及資源的分佈式事務。當事務工做時,事務管理器會進行監督。當有新的服務加入事務,以及訪問到的資源都會與這個事務關聯。服務執行業務邏輯資源,資源記錄事務內所作的修改。在事務期間,全部的服務(參與到事務裏的客戶端)必須經過投票決定它們是否提交事務或終止事務。
當事務結束時,事務管理器會檢查參與事務投票的全部服務。若是任何一個服務或客戶端投票終止事務,事務就不會提交:全部在事務期間對資源的修改都會被拋棄。若是全部的參與者都投票提交事務,那麼就會啓動兩階段提交協議:
第一階段,事務管理器詢問參與到事務裏的全部資源是否對於提交事務期間的修改還有什麼意見。注意,事務管理器不會命令資源提交修改,而只是詢問它們的意見。第一階段結束時,事務管理器會綜合全部的資源投票結果。
第二階段,根據投票結果來執行。若是全部的資源都投票提交事務,那麼事務管理器會告訴全部的資源提交修改。可是,若是任何一個資源沒有提交修改,那麼資源管理器會告訴其他的資源回滾修改,而後終止事務,並把系統恢復到事務以前的狀態。
資源管理器(RM)是由某個事務管理器管理的、支持原子操做和兩階段提交協議的資源。這個資源必須能夠檢測本身是否被包含進了事務,並且是否有且只有一次的自動那個加入事務列表。RM能夠處理持久化和非持久化資源,好比,事務性整數、字符串和集合。雖然RM必須支持兩階段提交協議,可是,他能夠選擇使用優化協議。這個協議稱爲一階段提交協議,事務管理器(TM)會一次性通知事務管理器執行的結果。
資源管理器在整個事務模型中主要承擔以下幾種職能:
- 幫助應用實現對目標資源的操做;
- 註冊到相應的事務管理器,以便事務回滾得時候能夠從事務管理器中接收到恢復請求,實現對數據的恢復;
- 向相應的事務管理器報告本地事務的結果;