當訊息佇列和事務聯系在一起時,它指的是訊息生產者和訊息消費者之間如何保持資料一致性,
什么是分布式事務?
事務是指當我們進行若干項資料更新操作時,為了保證資料的完整性和一致性,我們希望這些更新操作要么都成功,要么都失敗,而更新的資料,并不局限于資料庫中的資料,它可以是磁盤上的檔案,也可以是一個遠程服務,或者以其他形式存盤的資料,
事務會有四個特性,俗稱ACID:
- 原子性(A),一個事務操作不可分割,要么成功,要么失敗,
- 一致性(C),指資料在事務執行完成的時間之前,讀到的一定是更新前的資料,之后讀到的一定是更新后的資料,不存在一個時刻,讓用戶讀到更新程序中的資料,
- 隔離性(I),一個事務的執行不應該被其他事務干擾,
- 持久性(D),一個事務一旦完成提交,后續的其他操作和故障都不會對事務的結果產生影響,
對于分布式系統來說,嚴格實作ACID幾乎是不可能的,或者說代價太過,因此,我們在保證可用性和不嚴重犧牲性能的前提下,實作資料一致性已經很困難,因此,出現了很多變種,例如順序一致性、最終一致性等,
目前大家所說的分布式事務,更多情況下,是在分布式系統中事務的不完整實作,在不同的應用場景中,有不同的實作,目的都是通過一些妥協來解決實際問題,
在實際應用中,比較常見的分布式事務有2PC(Two-phase Commit,二階段提交)、TCC(Try-Confirm-Cancel)和事務訊息,
事務訊息使用的場景主要是那些需要異步更新資料,并且對資料實時性要求不太高的場景,
訊息佇列如何實作分布式事務?
事務訊息需要訊息佇列提供相應的功能才能實作,Kafka和RocketMQ都提供了事務相關功能,
下面以下訂單為例,說明一下如何使用訊息佇列實作分布式事務,
首先,訂單系統在訊息佇列上開啟一個事務,然后訂單系統給訊息服務器發送一個“半訊息”,這個半訊息不是說訊息內容不完整,它包含完整的訊息內容,半訊息和普通訊息的唯一區別,是在事務提交之前,對于消費者來說,這個訊息時不可見的,
半訊息發送成功后,訂單系統就可以執行本地事務了,在訂單中創建一條訂單記錄,并提交訂單庫的資料庫事務,然后根據本地事務的執行結果決定提交或者回滾事務訊息,如果訂單創建成功,那么就提交事務訊息,購物車系統就可以消費到這條訊息繼續后續的流程,如果訂單創建失敗,就回滾訊息,購物車系統就不會受到這條訊息,這樣基本實作了“要么都成功,要么都失敗”的一致性要求,
那么當提交事務訊息時失敗了,應該怎么處理呢?對于這種情況,Kakfa的解決方案比較簡單粗暴,直接拋出例外,讓用戶自行處理,RocketMQ會使用事務反查的機制來解決事務訊息提交失敗的問題,訂單系統作為Producer,在提交或者回滾事務訊息時發生網路例外,RocketMQ的Broker沒有收到提交或者回滾的請求,Broker會定期去Producer上反查這個事務對應的本地事務的狀態,然后根據反查結果決定提交或者回滾這個事務,
我們的業務代碼中需要實作一個反查本地事務狀態的街口,告知RocketMQ本地事務是成功還是失敗,
下面是用RocketMQ進行事務處理的流程圖,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/546137.html
標籤:其他
