在分布式系統中實現的事務就是分布式事務,分布式系統的cap原則是:
是分布式事務主要是保證資料的一致性,主要有三種不同的原則
共同點:
orderservice監聽新訂單佇列中的訊息,獲取之後新增訂單,成功則往新訂單繳費佇列中寫訊息,中間新增訂單的過程使用jta事務管理,當新增失敗則事務回滾,不會往新訂單繳費佇列中寫訊息;
再比如user service 扣費成功後,往新訂單轉移票佇列寫訊息,這時ticket service 正在處理中或者處理中發生了失敗,這中間的過程中使用者檢視自己的餘額已經扣費成功,但票的資訊卻沒有,此時可以使用事務失敗回滾的方式依次回退,這種叫弱一致性;又或者可以把處理失敗的內容傳送至乙個錯誤佇列中,由人工處理等方式解決,這種叫最終一致性。
因為jta採用兩階段提交方式,第一次是預備階段,第二次才是正式提交。當第一次提交出現錯誤,則整個事務出現回滾,乙個事務的時間可能會較長,因為它要跨越多個資料庫多個資料資源的的操作,所以在效能上可能會造成吞吐量低。
1.start message transaction
2.receive message
3.start database transaction
4.update database
5.commit database transaction
6.commit message transaction ##當這一步出現錯誤時,上面的因為已經commit,所以不會rollback
複製**
這時候就會出現問題
xa與最後資源博弈
1.start message transaction
2.receive message
3.start jta transaction on db
4.update database
5.phase-1 commit on db transaction
6.commit message transaction ##當這一步出現錯誤時,上面的因為是xa的第一次提交預備狀態,所以可以rollback
7.phase-2 commit on db transaction ##當這一步出現錯誤時,因為message不是xa方式,commit後無法rollback
複製**
但這種相比不使用jta,已經很大程度上避免了事務發生錯誤的可能性。
共享資源
最大努力一次提交
jms最大努力一次提交+重試
1.start message transaction
2.receive message
3.start database transaction
4.update database #資料庫操作出錯,訊息被放回mq佇列,重試重新觸發該方法
5.commit database transaction
6.commit message transaction
複製**
上面這種時候沒有問題
1.start message transaction
2.receive message
3.start database transaction
4.update database
5.commit database transaction
6.commit message transaction #提交mq事務出錯,訊息放回至mq佇列,重試重新觸發該方法
複製**
可能存在問題:會重複資料庫操作,因為database transaction不是使用jta事務管理,所以database已經commit成功;如何避免,需要忽略重發訊息,比如唯一性校驗等手段。
鏈式事務管理
# 預設的datasource配置
# spring.datasource.url = jdbc:mysql://localhost:3307/user
# spring.datasource.username = root
# spring.datasource.password = 123456
# spring.datasource.driverclassname = com.mysql.jdbc.driver
spring.ds_user.url = jdbc:mysql://localhost:3307/js_user
spring.ds_user.username = root
spring.ds_user.password = 123456
spring.ds_user.driver-class-name = com.mysql.jdbc.driver
spring.ds_order.url = jdbc:mysql://localhost:3307/js_order
spring.ds_order.username = root
spring.ds_order.password = 123456
spring.ds_order.driver-class-name = com.mysql.jdbc.driver
複製**
自定義配置類檔案
@configuration
public class dbconfiguration
@bean
@primary
public datasource userdatasource
()
@bean
public jdbctemplate userjdbctemplate(@qualifier("userdatasource") datasource userdatasource)
@bean
@configurationproperties(prefix="spring.ds_order") #設定讀取在properties檔案內容的字首
public datasourceproperties orderdatasourceproperties
()
@bean
public datasource orderdatasource
()
@bean
public jdbctemplate orderjdbctemplate(@qualifier("orderdatasource") datasource orderdatasource)
}複製**
spring註解解釋(@primary、@qualifier)
實際呼叫類
public class customerservice
orderjdbctemplate.update(insert_order_sql, order) #沒有使用事務,直接提交
if(order.gettitle().contains("error2"))
}}複製**
關於上述過程的詳細說明:
因為使用了標籤 @transactional的方式,使其在乙個事務裡面執行
也就是同步到transaction manager上面,但是這邊的同步不是說事務的同步,只是同步資料庫連線的開關
特別說明: @transactional 如果沒有做任何配置的情況下,則會使用dbconfiguration類中@primart註解下的datasource,用它去做datasource connection
spring datasourceutils原始碼
spring datasourceutils 使用已有的connection,只是控制資料庫連線的釋放,不是事務。
鏈式事務管理器在 這個庫裡面
dbconfiguration類中新增一段
@bean
public platformtransactionmanager transactionmanager
()複製**
鏈結事務管理器(chaining transaction managers)
出現異常是否會有問題呢?
git**位址 ☚
git**位址 ☚
git**位址☚
public orderservice
}userservice.charge(dto); #呼叫user微服務
}複製**
#通過調節限定,只有第一次支付的時候才會扣餘額,被重複呼叫的時候就不會重複扣費用,通過paystatus判斷
update customer set deposit = deposit - $, paystatus = 'paid' where orderid = $ and paystatus = 'unpaid'
複製**
分布式事務實現思路
大體思路是對事務進行 手動控制事務的開啟提交。datasource connect transaction transtaction註解也是aop 自己編寫事務註解zdytranstaction實現transtration裡面的幾個方法,connect也是,對datasource connect t...
分布式事務 分布式事務的實現
如果在多個服務中需要對不同的資料庫進行操作。因為不同服務操作的資料庫都不同,所以保證在同乙個事務中完成操作顯然是不科學的。那實現分布式事務的思想 1 方法入口,建立一條日誌記錄,狀態定義為初始狀態,即儲存本條日誌記錄 可以儲存在資料庫中,也可以寫出到本地磁碟檔案 2 可以在非同步執行緒或在定時任務中...
分布式柔性事務之事務訊息詳解
訊息詳解 在 柔性事務之tcc詳解 和 柔性事務之saga詳解 兩文中我們詳細剖析了柔性事務的第乙個分支補償型事務。在 剛性事務總結和柔性事務概述 中我們介紹過的柔性事務包含補償型事務和通知型事務。通知型事務主要包含事務訊息和最大努力通知型分布式事務兩個組成。通知型事務的核心思想是通過mq來通知其他...