[譯] Spring 的分佈式事務實現-使用和不使用XA — 第三部分

其它建議

示例中的 ChainedTransactionManager 具備簡單的優勢:它不用爲可用的擴展和優化費心。另外一種方法是在第二個資源加入時,使用 Spring 中的 TransactionSychronization API 爲當前事務註冊一個回調。這是 best-jms-db 示例中的方法,其中關鍵特性是 TransactionAwareConnectionFactoryDataSourceTransactionManager 的組合。這種特殊狀況能夠擴展泛化到使用 TransactionSynchronizationManager 的非 JMS 資源上。優勢是,原則上只有加入該事務的那些資源將被登記,而不是鏈中的全部資源。然而,配置仍然須要知道潛在事務中的參與者對應於哪些資源。html

此外,Spring 工程團隊正在爲 Spring Core 考慮開發「Best Efforts 1PC 事務管理器」功能。若是你喜歡該模式,而且但願在 Spring 中看到對它的明確和更透明的支持,你能夠在這個 JIRA 問題中投票。前端

非事務訪問模式

非事務訪問模式在某種特殊的業務流程中才有意義。這裏是指,有時你須要訪問的資源是邊緣的,不須要在事務中。例如,你可能須要向審計表中插入一行,該行與業務事務是否成功無關,它只是記錄了嘗試作某事。更常見的是,人們高估了他們須要對一個資源進行讀寫更改的程度,每每只讀訪問就足夠了。或者寫操做能夠被在更細粒度上加以控制,使得在寫操做中出現錯誤時,錯誤能夠被考慮或忽略。java

在這些狀況下,保持在事務以外的資源可能實際上具備它本身的事務,可是它不與正在發生的任何事務同步。若是你使用 Spring,則主要事務由 PlatformTransactionManager 驅動,邊緣資源多是從不禁事務管理器控制的數據庫「鏈接」從「數據源」獲取。全部這一切都發生在每一個訪問邊緣資源的默認設置是 autoCommit = true 時。讀操做不會看到在另外一個未提交的事務中同時發生的更新(假設有合理的默認隔離級別),可是寫操做的效果一般會被其餘參與者當即看到。android

這種模式須要更仔細的分析和更多設計業務流程的信心,但它不是徹底不一樣於 Best Efforts 1PC。當出現任何問題,提供補償事務的通用服務對於大多數項目來講是不現實的。可是簡單的使用狀況涉及冪等的、只執行一個寫操做(可能屢次讀)的服務並不罕見。這些是非事務性情境的理想狀況。ios

飛行之翼:反模式

最後一個模式是一個反模式。它每每出如今開發人員不瞭解分佈式事務或不知道他們已經實現了一個分佈式事務的狀況下。若是沒有顯式調用底層資源的事務 API,你不能只是假設全部的資源都加入一個事務。若是你使用除 JtaTransactionManager 以外的 Spring 事務管理器,就會有一個事務資源依附到這個模式。該事務管理器將用於使用 Spring 聲明性事務管理功能(如 @Transactional)來攔截方法執行。不能指望在同一事務中登記其餘資源。一般的結果是正常狀況下一切沒有問題,但只要有一個異常,用戶會發現其中一個資源沒有回滾。致使此問題的典型錯誤是使用 DataSourceTransactionManager 和使用 Hibernate 來實現倉庫。git

該使用哪一個模式呢?

我將經過分析這些模式的利弊得出結論,幫助你瞭解如何在它們之間作出決定。第一步是確認你有一個須要分佈式事務的系統。一個必要的(但不是充分的)條件是存在具備多於一個事務資源的單個進程;一個充分的條件是這些資源在單個用例中一塊兒使用,一般由對你的架構中的服務級別的調用驅動。github

若是你尚未分辨出分佈式事務,你可能已經實現了飛行之翼模式。早晚你會看到應該已回滾但並無回滾的數據。可能在真實的錯誤發生好久後你才能看到所形成的影響,這時已經很難追溯回失敗的源頭。開發人員可能會不當心使用飛行之翼模式,由於他們認爲 XA 已經在發揮做用,但實際上沒有配置基礎資源來參與事務。我曾經在一個項目上工做,其中數據庫已被另外一個組安裝,而且在安裝過程當中關閉了 XA 支持。系統運行了好幾個月,而後奇怪的錯誤開始滲透到業務流程中。診斷這個問題花了很長時間。spring

若是你的混合資源用例很簡單,能夠負擔得起分析和重構,那麼非事務資源模式多是一種選項。當其中一個資源主要是讀取,寫入操做能夠經過對重複項的檢查來保護時,這種模式最有效。即便在失敗以後,非事務性資源中的數據也必須在業務中有意義。審覈、版本控制和日誌記錄信息一般適用於此類別。在這個模式中,失敗將是相對常見的(任什麼時候候都有可能發生事務回滾),但你能夠相信這個沒有反作用。數據庫

Best Efforts 1PC 適用於要求失敗率低,且不但願有像 2PC 那麼大的開銷的系統。選擇這個模式帶來的性能提高是很顯著的。它的設置比非事務性資源更爲棘手,但它不須要那麼多的分析,而且用於更通用的數據類型。絕對的數據一致性要求業務處理對「外部」資源(除第一次之外的任一次提交)都是冪等的。消息驅動的數據庫更新是一個完美的例子,Spring 對它已經有至關好的支持。更不常見的狀況須要一些額外的框架代碼(這些框架代碼可能最終會是 Spring 的一部分)。後端

共享資源模式很是適用於特殊狀況,一般涉及兩個特定類型和平臺的資源(例如 ActiveMQ 與任何 RDBMS 或 Oracle AQ 與 Oracle 數據庫位於同一位置)。這個模式的優勢是極強的魯棒性和卓越的性能。

樣例代碼更新

因爲 Spring 版本的新版本和其餘組件的發佈,本文提供的示例代碼將不可避免地過期。請參閱 Spring 社區網站以訪問做者的最新代碼,以及 Spring Framework 和相關組件的最新版本。

Full XA with 2PC 是通用的,而且老是有最高的置信度、最強的保護以防止在使用多個不一樣資源的狀況下發生故障。缺點是,這個模式很昂貴,由於協議規定了額外的 I/O(但不要寫,直到你嘗試它),還須要特殊用途的平臺。有開源 JTA 實現了這種模式,能夠提供擺脫應用程序服務器的方法,但許多開發人員仍然認爲這種方式是次優的。固然,更多人沒有花時間思考他們系統中的事務邊界就選擇了使用使用 JTA 和 XA。至少若是他們使用 Spring,他們的業務邏輯就不須要知道事務是如何被處理的,所以能夠延遲平臺選擇。

Dr. David Syer 是 SpringSource 的首席顧問,常駐英國。他是 Spring Batch 項目的創始人和首席工程師,Spring Batch 是一個用於構建和配置離線和批處理應用程序的開源框架。他常常主持關於企業 Java 和行業評論員的會議。最近的出版物能夠在 The Server Side, InfoQ 和 SpringSource 博客找到。

更多參考資料

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索