我應該使用 XA 嗎
常見問題 > JMS > 我應該使用 XA 嗎
我應該使用 XA 交易(兩階段提交)嗎?
JMS 的常見用途是從佇列或主題中取用訊息,使用資料庫或 EJB 處理它們,然後確認/提交訊息。
如果您使用多個資源;例如讀取 JMS 訊息並寫入資料庫,您真的應該使用 XA - 其目的是為多個交易資源提供原子交易。例如,從您完成更新資料庫並提交變更,到您提交/確認訊息之間,有一個小的時間窗口;如果在此窗口內發生網路/硬體/處理程序故障,該訊息將被重新傳遞,您可能會最終處理重複的訊息。
XA 的問題在於它可能會有點慢;因為 XA 協議需要多次同步到磁碟,以確保它在所有可能的失敗情況下始終可以正確恢復。這增加了顯著的成本(在延遲、效能、資源和複雜性方面)。而且,相當多的 EJB 伺服器和資料庫實際上並不完全支援 XA!
請小心
ActiveMQ Classic 目前不支援 XA 交易暫停/恢復語義。
XA 的替代方案
因此,一個好的優化方法是使用常規的 JMS 交易 - 沒有 XA - 只是在您的程式碼中執行一些重複訊息偵測,以檢查您是否已處理過該訊息。
或者在偽程式碼中,您可以使用類似以下的方法…
onMessage
try {
if I have not processed this message successfully before {
do some stuff in the database / with EJBs etc
jdbc.commit() (unless auto-commit is enabled on the JDBC)
}
jms.commit()
} catch (Exception e) {
jms.rollback()
}
這導致了更好的效能,因為您沒有為 XA 協議執行許多慢速同步到磁碟(每個交易!)。這種方法的唯一缺點是它意味著您必須使用一些應用程式特定的邏輯來偵測您是否之前已處理過該訊息。但是,您通常會有一些方法可以偵測到這一點。例如,如果訊息包含採購訂單和版本;您是否已將該採購訂單和版本儲存在資料庫中?
因此,只要訊息具有某種 ID 和版本,您通常可以自行偵測重複項,因此不需要支付 XA 的效能成本
也值得閱讀我應該使用交易嗎。
進一步優化
執行重複偵測可能會增加效能開銷。例如,執行資料庫查詢以查看您是否之前處理過採購訂單等。大多數時候事情都會正常運作;只有在極少數情況下(例如,伺服器在處理某些訊息的中途崩潰),訊息才會被重新傳遞。
因此,您可以使用Message.getJMSRedelivered()方法來偵測訊息是否已被重新傳遞,並且僅當訊息被重新傳遞時才執行重複偵測檢查。