RocketMQ事務處理方案

2021-08-25 17:27:00 字數 1695 閱讀 4426

先討論一下什麼是事務訊息以及支援事務訊息的必要性。我們以乙個轉帳的場景為例來說明這個問題:bob向smith轉賬100塊。

在單機環境下,執行事務的情況,大概是下面這個樣子:

單機環境下轉賬事務示意圖

當使用者增長到一定程度,bob和smith的賬戶及餘額資訊已經不在同一臺伺服器上了,那麼上面的流程就變成了這樣:

集群環境下轉賬事務示意圖

這時候你會發現,同樣是乙個轉賬的業務,在集群環境下,耗時居然成倍的增長,這顯然是不能夠接受的。那如何來規避這個問題?

大事務 = 小事務 + 非同步

將大事務拆分成多個小事務非同步執行。這樣基本上能夠將跨機事務的執行效率優化到與單機一致。轉賬的事務就可以分解成如下兩個小事務:

小事務+非同步訊息

圖中執行本地事務(bob賬戶扣款)和傳送非同步訊息應該保證同時成功或者同時失敗,也就是扣款成功了,傳送訊息一定要成功,如果扣款失敗了,就不能再傳送訊息。那問題是:我們是先扣款還是先傳送訊息呢?

首先看下先傳送訊息的情況,大致的示意圖如下:

事務訊息:先傳送訊息

存在的問題是:如果訊息傳送成功,但是扣款失敗,消費端就會消費此訊息,進而向smith賬戶加錢。

先發訊息不行,那就先扣款吧,大致的示意圖如下:

事務訊息-先扣款

存在的問題跟上面類似:如果扣款成功,傳送訊息失敗,就會出現bob扣錢了,但是smith賬戶未加錢。

這裡需要說明一下:如果使用spring來管理事物的話,大可以將傳送訊息的邏輯放到本地事物中去,傳送訊息失敗丟擲異常,spring捕捉到異常後就會回滾此事物,以此來保證本地事物與傳送訊息的原子性。

rocketmq支援事務訊息,下面來看看rocketmq是怎樣來實現的。

rocketmq實現傳送事務訊息

rocketmq第一階段傳送prepared訊息時,會拿到訊息的位址,第二階段執行本地事物,第三階段通過第一階段拿到的位址去訪問訊息,並修改訊息的狀態。

細心的你可能又發現問題了,如果確認訊息傳送失敗了怎麼辦?rocketmq會定期掃瞄訊息集群中的事物訊息,如果發現了prepared訊息,它會向訊息傳送端(生產者)確認,bob的錢到底是減了還是沒減呢?如果減了是回滾還是繼續傳送確認訊息呢?

(回滾:即將執行另外的sql進行資料回滾)

rocketmq會根據傳送端設定的策略來決定是回滾還是繼續傳送確認訊息。這樣就保證了訊息傳送與本地事務同時成功或同時失敗。

分布式事務處理方案

首先,謝謝各位大神的指點。結合工作中遇到的問題和目前我了解到的分布式處理方案來簡單談談。1.事務的特性 事務必須滿足傳統事務的acid特性,即原子性,一致性,分離性和永續性。原子性 即最小單位的原子,要不全部成功,要不全部失敗。永續性 事務完成以後,持久的的儲存在資料庫,不會回滾。2.本地事務 本地...

PB事務處理

1 資料視窗更新,只要dberror有錯誤,而事先沒有做過任何commit工作,那麼rollback可以回滾到上次commit位置,即上次commit後所有的資料將被回滾。2 如果是直接寫入sql語句,只要資料庫出現錯誤,那麼rollback可以回滾到上次commit的位置,即上次commit後所有...

MySQL事務處理

start transaction,commit和rollback語法 start transaction begin work commit work and no chain no release rollback work and no chain no release set autocom...