天天看點

Distributed transactions in Spring without XA # Shared Transaction Resource pattern

文章目錄

  • ​​概述​​
  • ​​ORM架構和Spring JDBC​​
  • ​​消息驅動的單個資料庫更新​​
  • ​​基于ActiveMQ實作消息驅動的單個資料庫更新場景​​
  • ​​基于Kafka實作消息驅動的單個資料庫更新場景​​
  • ​​參考​​

概述

​​Distributed transactions in Spring, with and without XA​​一文中描述了在Spring中實作分布式事務的7種處理模式;3種基于XA協定,4種特定場景的非XA協定的模式;

共享事務資源模式(Shared Transaction Resource pattern)是四種非XA協定的第一種,其提供了特定場景的多資源事務同步模式;

熟悉Spring 事務架構的看到Transaction Resource應該立馬就明白了,Transaction Resource就是JDBC裡的Connection對象,Hibernete裡的Session對象,以此類比;

像JDBC的Connection,Hibernete的Session等如果要共享,也就意味着兩個事務使用的是同一個連接配接,也就意味着不再有分布式事務一說,兩個系統的操作真的是在同一個事務之中。

ORM架構和Spring JDBC

先描述一下文中的兩個例子:

第一個是ORM架構和JDBC,這是一個好像不是分布式事務的例子,在這裡我們描述的更具體一些,将JDBC換乘Spring JDBC,讓他看上去更像分布式事務一些,了解這個例子是基礎,一定要仔細看看:

在基于Spring架構的應用中,如果同時使用了ORM架構Hibernete和Spring JDBC一起操作資料庫,那麼如何将Spring JDBC的事務和Hibernete的事務進行同步呢?

答案就是共用一個JDBC Connection對象,Spring JDBC封裝了Java JDBC,Hibernete也是基于JDBC建構的,也就是說如果在Spring JDBC 和 Hibernete中使用同一個Java JDBC Connection對象,就可以實作事務的同步,其實根本就是在一個JDBC 事務中。

消息驅動的單個資料庫更新

文中提到共享事務資源模式的典型應用場景是消息驅動的單個資料庫更新。這是一個看上去就需要分布式事務同步場景。

基于ActiveMQ實作消息驅動的單個資料庫更新場景

文中同時舉了一個ActiveMQ + JDBC的例子,ActiveMQ是JMS協定的實作,同時ActiveMQ支援可配置的消息存儲的,其中就可以将ActiveMQ的隊列中的消息存儲到關系型資料庫中。

當把ActiveMQ把消息存儲到關系型資料庫中之後,如果我們後續的消息的業務處理之後的結果,也寫到同一個資料庫中,那ActiveMQ中消息的更新和業務系統中消息的處理結果持久化就可以共用一個資料庫連接配接了。

可以共用一個資料庫連接配接,也就意味着不再牽扯到分布式事務;

基于Kafka實作消息驅動的單個資料庫更新場景

這裡在送大家一個特定的例子,基于Kafka實作消息驅動的單個資料庫更新的場景。上邊的例子有着很大的性能問題,而基于Kafka實作消息驅動的單個資料庫更新的場景就像是天造地設一般。

Kafka消息隊列裡的讀取進度是存儲在Consumer端的,在Kafka中,叫做Offset。也就是說,如果我們在拉取消息之後,将最新的offset和消息的處理結果,共用同一個事務資源,寫到一個地方,要麼一起成功,要麼一起失敗;如果發生Partition的重新配置設定,隻需要從存儲中讀取最近一次成功處理的那批消息的最大的offfset,然後讓Consumer,seek此offset即可。實際上Kafka Connect的很多實作,比如Kafka Connect HDFS就是這麼搞的。

參考