Spring分散式事務XA事務(兩段提交2PC)實現

banq發表於2017-04-10
在系統的早期階段,不需要分散式事務。隨著應用程式數量的增加,資料同步成為一個重要問題。在資料同步方面,很多公司付出了很多維護同步系統的費用。由此,引入了稱為XA(擴充套件體系結構)的兩階段提交協議。該協議為全域性事務處理提供類似ACID的屬性。在本文中,將嘗試在Spring框架中解釋XA事務和使用XA事務。

兩階段提交協議是分散式系統的原子承諾協議。該協議的名稱意味著由兩個階段組成。第一個是提交請求階段,其中事務管理器協調所有事務資源以便能提交或中止。在第二個階段,也就是提交階段,事務管理器決定根據每個事務資源的投票透過提交或中止來終止操作。接下來將介紹2PC協議的實現細節。

[img index=1]
XA事務需要每個XA資源的全域性事務ID和本地事務ID(xid)。每個XA資源都透過start(xid)方法登入到XA Manager。該方法告訴XA資源正在捲入事務(準備好進行操作)。之後,透過呼叫prepare(xid)方法實現了2PC協議的第一階段。此方法從XA資源請求OK或ABORT投票。XA資源從每個XA資源獲得投票後,如果XA資源傳送ABORT,所有XA資源都會傳送OK或決定執行回滾(xid),則XA Manager決定執行提交(xid)操作。最後,為每個XA資源呼叫end(xid)方法,告訴事務完成。

由於網路丟失,機器關機以及某些管理員的錯誤,故障可能隨時發生。在XA交易中,我們將根據它們發生的階段對這些故障進行分類。故障首先發生階段可能是協議開始之前。這是一個簡單的故障,系統不需要回滾或任何型別的操作。我們只是不做這個特定時刻的操作。準備(提交 - 請求)階段可能也會發生故障,可以透過使用超時策略進行回滾來輕鬆處理。最後但並非最不重要的是由於不完整的回滾和回滾鏈中的任何問題而可能發生的提交階段故障。在上述所有這些情況下,事務管理器嘗試恢復問題。接下來我們將看到事務管理器如何嘗試克服失敗。

對於恢復,事務管理器呼叫每個XA資源的恢復方法。XA資源跟蹤日誌並嘗試重建其最新狀態。事務管理器呼叫必要的回滾操作,並完成任務。這個過程似乎是快樂的道路,但有很多異常情況,日誌有問題,如被破壞。在這種情況下,事務管理器採用一些啟發式解決問題。此外,恢復過程取決於在應用之前編寫操作日誌的預寫日誌。對於效能問題,這些日誌是以自己的格式編寫的(不使用任何序列化),如果可能,系統應該更好地對其進行批處理。接下來我們來討論Spring框架的XA事務支援的有趣的部分。

Spring框架為開發Web和獨立應用程式提供了廣泛的環境。像其他提供的實用程式一樣,Spring也支援XA事務。但是,這種支援並不是本地實現,而是需要hibernate支援,或者web容器提供XA事務管理的框架。Spring有JtaTransactionManager,它提供事務管理實用程式並隱藏細節。透過這種方式,我們可以為同時更新的多個DataSource進行事務管理。當涉及使用XA事務管理時,對XA事務的hibernate和web容器支援有很多文章,這裡不需要提及。但是,單獨提供XA事務的框架可能會令人抓狂。因此,這裡介紹Bitronix事務管理器

Bitronix易於配置,同時為事務管理提供良好的支援。它不常用於獨立應用程式,但下面嘗試為獨立應用程式配置如下:

<bean id="bitronixTMConfig" factory-method="getConfiguration"  class="bitronix.tm.TransactionManagerServices">
    <!--Disabling Jmx avoids registering JMX Beans to any container-->
    <property name="disableJmx" value="true" />
</bean>
<bean id="bitronixTM" factory-method="getTransactionManager" class="bitronix.tm.TransactionManagerServices" depends-on="bitronixTMConfig" destroy-method="shutdown"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="bitronixTM" />
    <property name="userTransaction" ref="bitronixTM" />
    <property name="allowCustomIsolationLevels" value="true" />
</bean>
<p class="indent">


我們現在可以有多個資料來源配置。每個資料來源應具有唯一的唯一名稱屬性。以下配置是針對Oracle,其他資料庫可以有不同的配置。對於任何其他細節,您可以檢視Bitronix網站。

<bean id="xaDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
    <property name="uniqueName" value="xaDataSource" />
    <property name="minPoolSize" value="1" />
    <property name="maxPoolSize" value="4" />
    <property name="testQuery" value="SELECT 1 FROM dual" />
    <property name="driverProperties">
        <props>
    <prop key="URL">jdbc:oracle:thin:@10.6.86.24:1521:test</prop>
            <prop key="user">test</prop>
            <prop key="password">test</prop>
        </props>
     </property>
     <property name="className" value="oracle.jdbc.xa.client.OracleXADataSource" />
     <property name="allowLocalTransactions" value="true" />
</bean>
<p class="indent">


XA Transactions (2 Phase Commit): A Simple Guide -

[該貼被banq於2017-04-11 09:18修改過]

相關文章