您好,登錄后才能下訂單哦!
本篇文章為大家展示了XA式、非XA式Spring分布式事務的實現是怎樣的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
Java Transaction API和XA協議是Spring常用的分布式事務機制,不過你可以選擇選擇其他的實現方式。理想的實現取決于你的應用程序使用何種資源,你愿意在性能、安全、系統穩健性、數據完整方面做出何種權衡。在這次JavaWorld大會上,來自SpringSource的David Syer跟大家分享了Spring應用的幾種事務處理機制、三種XA式、四種非XA式事務協議。
Spring框架支持Java Transaction API(JTA),這樣應用就可以脫離Java EE容器,轉而利用分布式事務以及XA協議。然而即使有這樣的支持,XA開銷是昂貴的,不穩定而且笨重不利于管理,不過一些其他的應用可以避免使用XA協議。
為了讓大家對所涉及的幾種分布式事務有所了解,我會分析七種事務處理模式,并 給出具體代碼實現。并且從安全或者穩定性入手倒序展示,可以看看從安全、穩定性出發,如何在一般場景下,保障數據高完整性和原子性。當然隨著話題的深入, 更多的說明以及限制就會出現。模式也可以從運行時開銷倒序展示。考慮到所有模式都是結構化或者學術性的,這一點有別于業務模型,因此我不打算展開業務用例 分析,僅僅關注每種模式其少部分代碼如何工作的。
盡管只有起初的三種模式涉及到 XA協議,不過從性能角度出發,這些模式或許無法滿足需求。考慮到這些模式無處不在,我不想做過多地擴展,只是對第一種模式做一個簡單的展示。讀完此文,你可以了解可以用分布式事務做些什么、不能做什么以及如何、何時避免使用XA,何時必須使用。
分布式事務涉及不止一個事務資源。比如,在關系數據庫和消息中間件之間通信的連接器,通常這些資源擁有類似begin()、rollback()、commit()的API。在此,一個事務資源通常是一個工廠產品,這個工廠通常由底層平臺提供:以數據庫為例,DataSource提供Connection,或者Java Persistence API(JPA)的EntityManager接口;又如Java Message Service(JMS)提供的Session。
一個典型的例子,一個JMS消息觸發一次數據庫更新。此過程可以分解成一時間線,一個成功的交互順序是下面這樣:
開啟消息事務
接受消息
開啟數據庫事務
更新數據庫
提交數據庫事務
提交消息事務
如果數據庫出錯,比如更新時出現諸如違反約束的問題,一個理想的順序應該是下面這個樣子:
開啟消息事務
接受消息
開啟數據庫事務
更新數據庫失敗
回滾數據庫事務
回滾消息事務
在這個案例中,最后的回滾發生后消息返回給中間件,并且在某種程度返回的消息會被其他事務所接收。通常這是件好事,可能你并沒有對失敗做記錄。自動重試處理異常機制超出了本文的范疇。
以上兩種時間線中最重要的特性是它們的原子性,形成一個單一的邏輯事務單元,要么都成功要么都失敗。
那么用什么確保時間線會的順序呢?事務資源之間必須保持某種同步,一旦對某個數據源做提交,要么都提交了,要么都回滾。否者整個事務就不缺乏原子性。之所以是分布式事務,是因為有多個數據源,沒有同步就沒有原子性。分布式事務技術和概念的核心問題都是圍繞資源的同步或者無法同步展開的。
前三種模式的以下討論都是基于XA協議,考慮到這三種模式分布廣泛,本文不會涉及太多的細節,倘若你熟悉XA模式或許愿意直接跳到共享事務資源模式。
如果你需要近乎完美的防護 (close-to-bulletproof)確保你的應用事務在斷電后恢復以及服務器崩潰,完整XA是不二之選。共享資源通常需要做事務同步,在此情況下,它是一個采用XA協議協調處理過程的信息特殊的事務管理器。在Java領域,從開發者的角度看,這個協議是通過JPA UserTransaction暴露給大家。
基于系統接口,XA作為一種促成科技(enabling technology)對多數開發人員不可見,因此他們需要知道XA在哪、促成什么、耗損如何以及如何利用事務資源。事務管理器采用二階段提交(2PC)協議,在確保事務結束前所有資源采用同一個事務結果的同時,也會帶來性能耗損。
如 果是Spring促成的(Spring-enabled),應用會采用Spring的JtaTransactionManager以及Spring聲明式 事務管理,這樣會隱藏到了底層事務同步的具體細節。對于開發人員用沒用XA的差別就在于對工廠資源的配置:DataSource實例,以及應用的事務管理 器。本文會通過一個應用案例(atomikos-db項目)來揭示這個配置,數據庫實例和事務管理器僅是XA或者JTA特定的應用元素。
為了揭示此案例如何工作,在com.springsource.open.db.下運行這個單元測試。一個簡單的 MulipleDataSourceTests類僅是將數據插入兩個數據源中,并且采用Spring整合支持的特性對事務進行回滾,代碼見清單1:
清單1、事務回滾
@Transactional @Test public void testInsertIntoTwoDataSources() throws Exception { int count = getJdbcTemplate().update( "INSERT into T_FOOS (id,name,foo_date) values (?,?,null)", 0, "foo"); assertEquals(1, count); count = getOtherJdbcTemplate() .update( "INSERT into T_AUDITS (id,operation,name,audit_date) values (?,?,?,?)", 0, "INSERT", "foo", new Date()); assertEquals(1, count); // Changes will roll back after this method exits }
接著驗證這兩個操作是否同時回滾,代碼清單如清單2:
清單2、回滾驗證
@AfterTransaction public void checkPostConditions() { int count = getJdbcTemplate().queryForInt("select count(*) from T_FOOS"); // This change was rolled back by the test framework assertEquals(0, count); count = getOtherJdbcTemplate().queryForInt("select count(*) from T_AUDITS"); // This rolled back as well because of the XA assertEquals(0, count); }
更進一步理解Spring事務管理如何工作以及如何配置,請參看Spring參考指南。
許多事務管理器采用這種優化模式,可以避免單一事務資源下的2PC過度開銷,你的應用服務器最好能夠判別此種情況。
多數XA事務管理器另一個特性是,不論是單一XA兼 容資源還是所有資源都XA兼容,事務管理器均能提供相同的恢復保障。它們是通過給資源排序,并且給非XA資源投票實現,倘若事務提交失敗,所有其他的資源 都能回滾。事務有近乎百分百的保障,但缺點是,倘若事務失敗,此時不會留下太多信息。換言之,如果要獲取這些信息,需要做一些額外的步驟,比如在一些高級實現。
這個模式不錯,系統所有的事務資源由一個相同的資源提供支持進而移除XA,降低系統的復雜度,提高吞吐量。當然不能拿來處理所有的用例,但卻是如XA般堅固,而且處理速度更加的快。共享事務資源模式作為一種保障存在與特定的平臺和處理場景中。
一個簡單熟悉的例子就是共享一個數據庫的Connection,它存在于一個對象關系模型(ORM)控件和一個JDBC控件之間。Spring事務管理器就是如此,它支持ORM工具,比如Hibernate、EclipseLink以及Java Persistence API(JPA)。相同的事務能安全的跨越ORM和JDBC控件之間,通常此事務是由service層受事務控制的執行方法所驅動的。
此模式的另外一個特點是,消息驅動的單個數據庫更新,如本文初始階段的簡單例子。消 息中間件系統需要存儲這些數據,通常是關系型數據庫。實現這種模式,需要將消息系統指定到相同的用于存儲業務數據的數據庫中。這種模式依賴消息中間件供應 商所提供的存儲策略細節,以便能夠將消息中間件配置在相同的數據庫中,并嵌入相同的事務處理。
不是所有的供應商都提供了此種模式,不過一種可替代,幾乎可以用于任何數據庫的方式,即利用Apache ActiveMQ的傳遞消息,并且插入一個存儲策略進入消息代理中。一旦你知道了其中的訣竅,配置起來很容易的,我會在本文的shared-jms-db 項目案例中演示。此模式的所用的代碼無需關注,它們會在Spring配置中得到聲明。
名為 SynchronousMessageTriggerAndRollbackTests 的案例中,單元測試校驗所有與同步消息接收者相關的訊息。 testReceiveMessageUpdateDatabase方法接受兩個消息,接著利用消息插入兩條記錄到數據庫中。如果此方法退出,測試框架回 滾事務,這樣就能校驗消息和數據庫更新是否發生回滾,如清單3所示:
清單3、驗證消息和數據庫更新是否回滾
@AfterTransaction public void checkPostConditions() { assertEquals(0, SimpleJdbcTestUtils.countRowsInTable(jdbcTemplate, "T_FOOS")); List<String> list = getMessages(); assertEquals(2, list.size()); }
配置文件最重要的部分就是ActiveMQ的持久化策略,連接消息系統和相同數據源作為業務數據,Spring JmsTemplate的flag標簽用來接收消息。清單4 展示了如何配置ActiveMQ持久化策略:
清單4、ActiveMQ持久化配置
<bean id="connectionFactory" depends-on="brokerService"> <property name="brokerURL" value="vm://localhost?async=false" /> </bean> <bean id="brokerService" init-method="start" destroy-method="stop"> <property name="persistenceAdapter"> <bean> <property name="dataSource"> <bean> <property name="targetDataSource" ref="dataSource"/> <property name="jmsTemplate" ref="jmsTemplate"/> </bean> </property> <property name="createTablesOnStartup" value="true" /> </bean> </property> </bean>
清單5展示了Spring JmsTemplate中用來接收消息的flag標簽:
清單5、設置JmsTemplate事務應用
<bean id="jmsTemplate"> <!-- This is important... --> <property name="sessionTransacted" value="true" /> </bean>
若 sessionTransacted不為true,JMS session transaction API就無法被調用,消息接受者將無法回滾。最為重要的是,嵌入的代理包含一個特殊的async=false參數以及DataSource外包類,這樣就可以確保ActiveMQ擁有同Spring一樣的事務JDBC Connection。
一個共享數據庫源可以由獨立的單個數據源組成,特別是這些數據源擁有同樣的RDBMS平臺。企業級數 據庫供應商均提供同名概念(the notion of synonyms)支持,表可以作為一個同名(synonyms)聲明于多個schema中。借助這個手段,分布在不同物理平臺上的數據,可以均可 JDBC client同意Connection事務管理。比如在一個真實的系統中,采用ActiveMQ共享資源模式實現,通常需要為消息和業務數據創建同名。
ActiveMQ 社區的一些開發人員表示JDBCPersistenceAdapter會引發性能問題。然而,許多項目和上線系統采用ActiveMQ與關系型數據庫搭配使 用。在這些案例中,公認的是日志版本的適配器可以用來提供性能,當然這對共享資源模式來說是不利的,因為日志本身就是一個新的事務資源。然而,對于 JDBCPersistenceAdapter大家眾說紛紜,看法不一。確實,有理由相信采用共享資源或許能提高日志案例的性能。這個一結論來自 Sping以及AtiveMQ工程師團隊的研究。
非消息場景(多個數據庫)的另一種共享資源技術就是,在RDBMS平臺一級利用Oracle數據庫鏈接一個特征到兩個數據庫schema中。或許這需要改變應用代碼,或者創建同名,因為表的別名會指向一個已鏈接數據庫,此數據庫包含鏈接的名稱。
開發人員必須知道,最大努力一次提交模式應用相當的普遍,但是在一些場景并不適用。這是一種非XA模式,它包含一 個同步大量資源單一相提交(single-phase commit)。參與者應該意識到這種折中,如果不用兩階段提交,那最大努力一次提交模式的安全性不如XA事務但也是相當不錯。許多海量數據、大吞吐量事 務處理系統用最大努力一次提交模式提高性能。
最基本的理念就是在單一事務中盡可能的延遲所有資源的提交,這樣唯一可能發生錯誤的就是基礎組件,而非業務處理錯誤。 采用最大努力一次提交模式的系統假定基礎組件出錯的可能性非常小,因此能夠承受風險獲得較高的吞吐量收益。如果業務處理服務也被設計為一個幕等式 (idempotent),發生錯誤的可能性也很小。(譯者注:幕等式是數學和計算機科學特定運算的一個特性,應用初始化以后多次操作其結果都不會再發生改變)
為了幫助大家更好的理解這個模式分析失敗結果,我會用消息驅動數據庫更新作為例子來加以說明。
本事務中兩個資源將被統計、并且計算。消息事務在一個數據庫之前開啟,然后逆序結束。成功的順序或許和本文開始的時候一模一樣:
開啟消息事務
接受消息
開啟數據庫事務
更新數據庫
提交數據庫事務
提交消息事務
準確的說,此順序前四個步驟都不重要,重要的是消息必須在數據庫更新之前被接受,并且每個事務必須在對應的資源被調用之前開啟,因此合理的順序應該如下:
開啟消息事務
開啟數據庫事務
接受消息
更新數據庫
提交數據庫事務
提交消息事務
關鍵點是最后兩步很重要,它們必須放在最后按順序執行。按序之所以重要,其本身就是一個技術問題,不過這個順序是有業務需 要決定的。這個順序告訴開發者,其中的一個事務資源是特殊的,這個資源包含了如何在其他資源上運作的指令。這是一個業務順序:系統不能自動告知走事務到哪一步了。即使消息和數據庫是兩個資源,事務也常常遵循這一流程。按序之所以重要,是因為事務必須處理失敗案例。迄今最常見的失敗案例是,諸如壞數據、編程錯誤等失敗的業務處理。本例中,這兩個事務很容易用來相應一個異常并且回滾。這樣,業務數據的完成性得到保障,時間線與本文開始列出的理想失敗案例神似。
引發回滾機制的精確性不是很重要的,這樣的機制有好一些。最重要的是,提交或者回滾必須按照資源中業務順序的逆序發生。在一個應用案例中,消息事務必須在最后提交,因為處理業務的指令包含在這個資源中,這是因為,很少有失敗案例 其第一次提交成功,第二次失敗。在這個點上,所有設計業務處理的部分都已完成,那唯一能引起部分失敗的因素,可能消息中間件的基礎問題。
注意如果 數據庫資源提交失敗,那么事務最終會發生回滾。所以是說非原子性失敗模型(failure mode)其第一個事務會提交,第二個事務發生回滾。通常,事務中有n個資源,那么就存在n-1個這樣的失敗模型,這會導致一個子事務回滾后,其它一些資源處在提交后的不一致狀態。在消息數據庫用例中,失敗模型的結局是,消息會回滾,然后是其他的事務,即使其他這些事務都經成功處理;可以斷定最糟糕的事情 就是重復消息(duplicate message)被傳遞過來。什么是重復消息呢?通常情況下,事務中的早期資源被認為是包含有后續資源處理流程的訊息,因此失敗模型的結果可以被認為就是重復消息。
一 些富有冒險精神的人認為重復消息發生的可能性微乎其微,因此懶得去預測這些消息。然而,為了更加確信業務數據是準確性和一致性,還是需要在業務邏輯層面對 此有清晰地認識。 如果懷疑重復消息可能發生,那么必須核實,業務處理過程是否處理過數據,在處理數據之前是否什么都沒做。這個特定的說明有時指幕等業務服務模型 (Idempotent Business Service pattern)。
相關案例包括兩個采用此模型的同步事務資源例子,我會在后面做一一分析,以及一些其它選項。
案例best-jms-db項目中的代碼,開發人員采用主流配置,這樣就可以使用最大努力一次提交模式。具體的做法是這樣的,通過一個異步的監聽器將消息傳給一個隊列,并將此數據插入 數據庫表中。
TransactionAwareConnectionFactoryProxy 是Spring的一個存儲控件,應用于這個模式中,也是最關鍵的組成部分。放棄采用供應商提供的粗顆粒度的 ConnectionFactory,configuration采用裝飾模式包裝了一個ConnectionFactory,用它來處理事務同步問題。 具體配置見jms-context.xml,如下清單6所示:
清單6、配置一個TransactionAwareConnectionFactoryProxy去包裝一個供應商提供的JMS ConnectionFactory
<bean id="connectionFactory"> <property name="targetConnectionFactory"> <bean depends-on="brokerService"> <property name="brokerURL" value="vm://localhost"/> </bean> </property> <property name="synchedLocalTransactionAllowed" value="true" /> </bean>
ConnectionFactory 無需知道哪個事務管理器與其同步,每一時刻僅有一個事務處在活動(active)狀態。這些是由Spring內部在處理。事務驅動是由配置在data- source-context.xml中的DataSourceTransactionManager完成的,事務管理器必須由輪詢和接受消息的JMS監聽器容器監控。
<jms:listener-container transaction-manager="transactionManager" > <jms:listener destination="async" ref="fooHandler" method="handle"/> </jms:listener-container>
fooHandler和方法會告知監聽器容器某個具體的控件的具體方法得到調用,當一個消息達到”異步”隊列。handler是如此實現的,接受一個String作為參數消息,并將其作為數據插入記錄中。
public void handle(String msg) { jdbcTemplate.update( "INSERT INTO T_FOOS (ID, name, foo_date) values (?, ?,?)", count.getAndIncrement(), msg, new Date()); }
為了模擬失敗,代碼用一個FailureSimulator切面,它會檢查消息內容是否真的失敗;如清單7所示,在FooHandler在事務結束之前,處理消息之后,maybeFail()方法得到調用,所以它能影響事務的結果。
清單7、maybeFail()方法
@AfterReturning("execution( ..*Handler+.handle(String)) && args(msg)") public void maybeFail(String msg) { if (msg.contains("fail")) { if (msg.contains("partial")) { simulateMessageSystemFailure(); } else { simulateBusinessProcessingFailure(); } } }
simulateBusinessProcessingFailure() 方法會拋出DataAccessException,就像數據庫訪問真的失敗。一旦這個方法被調用,最理想的結局是所有的數據庫以及消息事務都能回滾。 這個場景在案例項目AsynchronousMessageTriggerAndRollbackTests單元測試得到測試。
simulateMessageSystemFailure() 方法通過破壞底層的JMS Session來模擬消息系統失敗。預期的結果是事務部分提交:數據庫提交了,但消息回滾。這個在 synchronousMessageTriggerAndPartialRollbackTests單元測試驗證過。
同樣,在AsynchronousMessageTriggerSunnyDayTests類中,包含一個所有事務成功提交的單元測試。
相 同的JMS配置,相同的業務邏輯同樣可以用在同步的環境中,消息由存儲在業務邏輯中的阻塞請求所接收,而非監聽器容器。此方法在best-jms-db案 例項目中得到展示。 sunny-day case以及事務全部回滾分別在SynchronousMessageTriggerSunnyDayTests和 SynchronousMessageTriggerAndRollbackTests得到測試。
在其他的最大努力一階段提交模式案例中,一個粗糙的事務管理器實現僅僅是將一系列其他的事務管理器鏈接在一起,去實現事務同步。倘若業務處理成功,所有的事務將會提交, 否則它們都能回滾。
ChainedTransactionManager 接受一系列其他的事務管理器作為注入屬性,如清單8所示:
清單8、配置
<bean id="transactionManager"> <property name="transactionManagers"> <list> <bean> <property name="dataSource" ref="dataSource" /> </bean> <bean> <property name="dataSource" ref="otherDataSource" /> </bean> </list> </property> </bean>
此配置簡單的測試,僅是同時插入數據到兩個數據庫,回滾,同時確保兩個運行回滾到最初狀態。此實現作為存在MulipleDataSourceTests中的一個單元測試,如同XA案例中的 atomikos-db項目。倘若回滾沒有同步,有事務提交了,那測試就算失敗。
記 住,資源順序很重要,它們是嵌套的,提交或者回滾以它們參與的相反順序進行。其中一個事務最為特別:如果存在問題,最重要的事務會回滾,即便是這問題是一個資源失敗。 同樣,testInsertWithCheckForDuplicates()測試方法展示了幕等式業務處理如何從部分失敗中保護系統,此實現作為一個里層資源(otherDataSource)中業務運算防御檢測。
int count = otherJdbcTemplate.update("UPDATE T_AUDITS ... WHERE id=, ...?"); if (count == 0) { count = otherJdbcTemplate.update("INSERT into T_AUDITS ...", ...); }
update首先嘗試和一個where子句執行,不出意外,update中的數據會插入數據庫中。本例中的幕等式處理一個額外的花銷是sunny-day case中額外的查詢,這個額外的花銷在復雜的每個事務執行多個查詢的業務處理中微乎其微。
案例中的ChainedTransactionManager擁有簡潔優勢,而且擴展優化已做的很好。另一個方式是, 當第二個資源加入時,利用Spring的TransactionSychronization API給當前事務 注冊一個回調函數,此方式在best-jms-db案例中,最大的特點是TransactionAwareConnectionFactory和一個 DataSourceTransactionManager的結合。利用TransactionSynchronizationManager,這個特殊的案例可以擴展并且泛化到包含non-JMS的資源中。這樣理論上有個優勢,就是只有加入事務的資源得到支持,而非鏈上的 所有資源。然而配置依舊需要監聽某個潛在的事務與之對應的資源。
同樣,Spring工程師團隊考慮將最大努力一階段提交事務管理器特性作為Spring核心。你可以在JJRA issue中投票,如果你喜歡這種模式,希望Spring中顯示以及更加透明地支持此種模式。
非事務訪問模式需要一個特殊的業務處理,這樣才有意義。理想的狀態是有時,其中一些你需要訪問的資源邊緣化,一點都不需要事務。比如,或許你需要將一行數據插入一個 審核表中,此操作是獨立的,和業務事務是否成功無關。僅僅記錄試圖做了某事。更普遍的場景,人們高估了他們需要對其中一個資源做讀寫的頻次,事實上,只有 訪問就很好了。 否則,寫操作需要得到很好地控制,因此如果發生任何錯誤,寫操作可以被記錄下來或者忽略。
在以上的案例中資源恰當地原理全局事務,但仍然有其自己的本地事務,本地事務無需與其他發生的事情保持同步。如果你使用的是Spring,主要的事務由一個PlatformTransactionManager驅動, 邊緣資源或許是一個數據庫Connection,它來自一個不受事務管理器控制的DataSource。每一次訪問邊緣資源需要將缺省環境設為 autoCommit=true。updates對讀操作不可見,前者可以與其他非提交事務并發進行,但寫操作帶來的影響通常對其他操作來說是立即可見的。
這個模式需要更多精細地分析,以及更多自信去涉及業務處理,但它同最大努力一階段提交沒 什么區別。當任何事情出錯,一個通用的補償事務服務對多數項目來說太過龐大。不過簡單的用例所涉及的服務,它是幕等式的僅僅執行一個寫的操作,這種現象再 普通不過了。這些是非事務策略的理想場景。
最后一種模式是一種反模式,它出現這樣一個場景中,開發者不理解或者沒有意識到他們已經存在一個分布式事務時。無需顯示的調用底層的資源事務API,你不確 定所有的資源是否在一個事務中。倘若用的是一個Spring事務管理器而非JtaTransactionManager,此管理器會將一個事務資源加入其中。這個事務管理器將會攔截Spring聲明事務管理特性的執行方法,比如@Transactional;其他的資源不會注冊到相同的事務中。通常的結局 是任何事情都運轉正常,不過很快用戶會發現存在一個異常,其中一個資源沒有回滾。一個典型的錯誤導致的問題是利用一個 DataSourceTransactionManager以及一個利用Hibernate實現的倉庫。
我會通過分析已介紹過的模式其利弊,幫助大家做出取舍。第一步是分析你的系統是否需要分布式事務。一個必須但不充分條件是,存在不止一個事務資源的單一處理。充分條件是這些資源都在一個單獨的用例中,通常由系統架構的service層調用來驅動。
如果你不認為這是分布式事務,那最好采用Wing-and-a-Prayer模式,接著你會看見數據應該回滾但沒有。或許你會看到這種影響從失敗發生直至其下游一直存在,而且很難追溯回去。Wing-and-a-Prayer的 使用也可能會開發人員所疏忽,他們認為受到了XA保障,其實并沒與配置底層資源加入到事務中。我曾經做過一個這樣的項目,數據庫是其他人員搭建的,他們在 安裝數據庫的過程中關閉了XA支持。運行了個把月沒有任何問題,接著各種奇怪的失敗開始侵入業務處理中,需要花很長的時間去找出問題。
如果是一個包含異質資源的簡單用例,你可以分析甚至做一些重構,那么非事務訪問模式或 許是個不錯的選擇,特別是其中一個幾乎是只讀資源,雙檢測確保寫操作。即便是失敗了,非事務資源中的數據在業務術語中必須有意義。審核、版本控制、甚至日 志信息能很好的切入到此目錄中,失敗變得相對很平常—-任何時間真實事務中的任何事情都可回滾,但你需確信這樣做不存在負面影響就好。
對系統而言,最大努力一階段提交需要通用的失敗保護機制,但有不存在2PC那么大的開銷,而且性能得到極大的提升。相對非事務資源,它的建立需要更多的技巧,但無需太多的分析, 通常應用于更加通用的數據類型中。完成數據一致性的某些特性,需要保障業務處理對外層資源(”outer” resources:第一個提交的資源)而言是幕等式。消息驅動的數據庫更新就是一個完美的例子,并且在Spring中得到很好的支持。不常見的場景需要一些額外的框架代碼,這些代碼終究會成為Spring的一部分。
共享資源模式是一種特定的例子,通常涉及一個特定的類型和平臺兩個資源,比如,ActiveMQ和任何一個RDBMS或者OracleAQ與一個Oracle數據庫共存。這樣做最大的收益是相當的靈活以及出色的性能。
Full XA with 2PC是一種通用模式,在應對多個異質資源事務 失敗時提供很好的無憂保證。不利的是它的開銷很大,需要遵循特定的I/O協議和特定的平臺。有開源的JTA實現,提供了一種擺脫應用服務器的方式,但多數 開發人員依舊認為它們并非最好。可以確信的是,人們花更多的時間去思考系統的事務界限,會更傾向于使用他們并不那么需要的JTA和XA。至少使用 Spring的開發人員,他們的業務邏輯無需知道事務如何被處理的,暫時無需考慮平臺選擇的問題。
上述內容就是XA式、非XA式Spring分布式事務的實現是怎樣的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。