<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          深度剖析分布式事務(wù)之 AT 與 XA 對比

          共 3062字,需瀏覽 7分鐘

           ·

          2022-04-11 15:18

          AT 這種事務(wù)模式是阿里開源的seata主推的事務(wù)模式,本文會詳解AT的原理,并將它與XA模式進(jìn)行比較

          原理

          AT 從原理上面看,與 XA 的設(shè)計(jì)有很多相近之處。XA 是數(shù)據(jù)庫層面實(shí)現(xiàn)的二階段提交, AT 則是應(yīng)用/驅(qū)動層實(shí)現(xiàn)的二階段提交。建議您了解了XA相關(guān)的知識后,來閱讀這篇文章,這樣能夠更快更好的掌握 AT 的原理與設(shè)計(jì)。

          AT的角色和XA一樣分為3個,但是起了不一樣的名稱,大家注意分辨:- RM 資源管理器,是業(yè)務(wù)服務(wù),負(fù)責(zé)本地?cái)?shù)據(jù)庫的管理,與XA中的RM一致 - TC 事務(wù)協(xié)調(diào)器,是Seata服務(wù)器,負(fù)責(zé)全局事務(wù)的狀態(tài)管理,負(fù)責(zé)協(xié)調(diào)各個事務(wù)分支的執(zhí)行,相當(dāng)于XA中的TM - TM 事務(wù)管理器,是業(yè)務(wù)服務(wù),負(fù)責(zé)全局事務(wù)的發(fā)起,相當(dāng)于XA中的APP

          AT 的第一階段為prepare,它在這一階段會完成以下事情:1. RM 側(cè),用戶開啟本地事務(wù) 2. RM 側(cè),用戶每進(jìn)行一次業(yè)務(wù)數(shù)據(jù)修改,假設(shè)是一個update語句,那么 AT 會做以下內(nèi)容:1. 根據(jù)update的條件,查詢出修改前的數(shù)據(jù),該數(shù)據(jù)稱為BeforeImage 2. 執(zhí)行update語句,根據(jù)BeforeImage中的主鍵,查詢出修改后的數(shù)據(jù),該數(shù)據(jù)稱為AfterImage 3. 將BeforeImage和AfterImage保存到一張undolog表 4. 將BeforeImage中的主鍵以及表名,該數(shù)據(jù)稱為lockKey,記錄下來,留待后續(xù)使用 3. RM 側(cè),用戶提交本地事務(wù)時,AT 會做以下內(nèi)容:1. 將2.4中記錄的所有的lockKey,注冊到 TC(即事務(wù)管理器seata)上 2. 3.1中的注冊處理會檢查 TC 中,是否已存在沖突的主鍵+表名,如果有沖突,那么AT會睡眠等待后重試,沒有沖突則保存 3. 3.1成功完成后,提交本地事務(wù)

          如果 AT 的第一階段所有分支都沒有錯誤,那么會進(jìn)行第二階段的commit,AT 會做以下內(nèi)容:1. TC 會將當(dāng)前這個全局事務(wù)所有相關(guān)的lockKey刪除 2. TC 通知與當(dāng)前這個全局事務(wù)相關(guān)的所有業(yè)務(wù)服務(wù),告知全局事務(wù)已成功,可以刪除undolog中保存的數(shù)據(jù) 3. RM 收到通知后,刪除undolog中的數(shù)據(jù)

          如果 AT 的第一階段有分支出錯,那么會進(jìn)行第二階段的rollback,AT 會做以下內(nèi)容:1. TC 通知與當(dāng)前這個全局事務(wù)相關(guān)的所有業(yè)務(wù)服務(wù),告知全局事務(wù)失敗,執(zhí)行回滾 2. RM 收到通知后,對本地?cái)?shù)據(jù)的修改進(jìn)行回滾,回滾原理如下:1. 從undolog中取出修改前后的BeforeImage和AfterImage 2. 如果AfterImage與數(shù)據(jù)庫中的當(dāng)前記錄校驗(yàn)一致,那么使用BeforeImage中的數(shù)據(jù)覆蓋當(dāng)前記錄 3. 如果AfterImage與數(shù)據(jù)庫中的當(dāng)前記錄不一致,那么這個時候發(fā)生了臟回滾,此時需要人工介入解決 3. TC 待全局事務(wù)所有的分支,都完成了回滾,TC 將此全局事務(wù)所有的lockKey刪除

          問題分析

          AT 模式的一個突出問題是rollback中2.3的臟回滾難以避免。以下步驟能夠觸發(fā)該臟回滾:1. 全局事務(wù)g1對數(shù)據(jù)行A1進(jìn)行修改 v1 -> v2 2. 另一個服務(wù)將對數(shù)據(jù)行A1進(jìn)行修改 v2 -> v3 3. 全局事務(wù)g1回滾,發(fā)現(xiàn)數(shù)據(jù)行A1的當(dāng)前數(shù)據(jù)為v3,不等于AfterImage中的v2,回滾失敗

          這個臟回滾一旦發(fā)生,那么分布式事務(wù)框架沒有辦法保證數(shù)據(jù)的一致性了,必須要人工介入處理。想要避免臟回滾,需要把所有對這個表的寫訪問,都加上特殊處理(在Seata的Java客戶端中,需要加上GlobalLock注解)。這種約束對于一個上了一定規(guī)模的復(fù)雜系統(tǒng),是非常難以保證的。

          AT vs XA

          上述臟回滾問題,在 XA 事務(wù)中不會出現(xiàn),因?yàn)?XA 事務(wù)是在數(shù)據(jù)庫層面實(shí)現(xiàn)的,當(dāng)另一個服務(wù)對為數(shù)據(jù)行A1進(jìn)行修改時,會因?yàn)樾墟i被阻塞,與普通事務(wù)的表現(xiàn)完全一樣,不會產(chǎn)生問題。

          另外 XA 不會發(fā)生臟讀,而 AT 會發(fā)生臟讀,考慮AT下的如下執(zhí)行步驟:1. 全局事務(wù)g1對數(shù)據(jù)行A1進(jìn)行修改 v1 -> v2 2. 另一個服務(wù)將讀取數(shù)據(jù)行A1,獲得數(shù)據(jù) v2 3. 全局事務(wù)g1回滾,將數(shù)據(jù)行A1改回 v2 -> v1

          這里面步驟2讀取的數(shù)據(jù)是v2,是一個中間態(tài)數(shù)據(jù)。在Seata的手冊中,雖然也有一些方法能夠避免AT模式下,但是涉及到注解和sql改寫,并不優(yōu)雅。而在XA模式下,由于還沒有進(jìn)行xa commit,那么步驟2根據(jù)MVCC讀取到的數(shù)據(jù)依然是v1,沒有AT模式中的臟讀的困擾。

          性能分析

          從原理的詳細(xì)步驟看,XA事務(wù)的性能高于AT,分析如下:

          AT 模式下,RM側(cè),上述原理過程中,執(zhí)行的SQL如下:1. 開啟事務(wù) 2. 查詢BeforeImage數(shù)據(jù) 3. 執(zhí)行update 4. 查詢AfterImage數(shù)據(jù) 5. 將BeforeImage,AfterImage插入到undolog中 6. 提交事務(wù) 7. 事務(wù)完成后,刪除BeforeImage和AfterImage

          而 XA 模式下,RM側(cè),執(zhí)行的SQL如下:1. xa begin 2. 執(zhí)行update 3. xa end 4. xa prepare 5. xa commit

          兩者對比,相關(guān)的開啟/提交事務(wù)是兩個模式都需要的,性能差異不大。但是從執(zhí)行的DML操作來看,AT 下的 SQL 數(shù)量為:3 writes,2 read,比 XA 下僅一個update多出許多,因此在性能上會有較大的差距

          從上述理論分析,XA 事務(wù)性能會大幅高于AT,應(yīng)當(dāng)可以在postgres數(shù)據(jù)庫上驗(yàn)證出來;而mysql數(shù)據(jù)庫,在當(dāng)前的5.8版本上,由于xa prepare后,需要將當(dāng)前連接斷開才能夠在其他連接上xa commit,所以會有一個重新創(chuàng)建連接的開銷,最終性能對比參考下一節(jié)。

          性能實(shí)測

          上述進(jìn)行了理論上的性能分析,我同時也做了性能實(shí)測,詳細(xì)的測試過程和結(jié)果數(shù)據(jù),參考?xa-at bench

          dtm實(shí)現(xiàn)的XA事務(wù),為了在極端情況下,也能保證XA事務(wù)能夠正確的被清理,會在業(yè)務(wù)事務(wù)中對子事務(wù)屏障表進(jìn)行插入,因此會比上述理論分析中,多一個sql寫入。

          我們可以看到,最終的結(jié)果XA性能優(yōu)于AT。如果未來Mysql完善了XA的實(shí)現(xiàn),可以不用關(guān)閉當(dāng)前連接也能夠允許其他連接提交xa事務(wù),那么XA的性能還能夠提升一大截。

          AT的意義

          mysql在版本5.6中,xa相關(guān)API存在bug。如果當(dāng)前連接在xa prepare之后,連接斷開,那么這個連接未完成的事務(wù)會被自動回滾。這樣的bug導(dǎo)致mysql的XA模式是無法保證正確性的,在各種應(yīng)用crash中,可能導(dǎo)致數(shù)據(jù)不一致。因此AT在mysql的5.6版本及更低版本使用中,是具有很高應(yīng)用價值的。

          另外部分大廠的數(shù)據(jù)庫是禁止使用XA事務(wù)的,這種特定場景下,選型AT模式,也是合理的。

          對于其他場景,建議優(yōu)先考慮 XA 事務(wù)。

          小結(jié)

          作者對AT模式的完整實(shí)現(xiàn)源碼,并未完整閱讀。上述的相關(guān)原理是根據(jù)自己閱讀相關(guān)資料,并參考了seata-golang的源代碼而寫。文中如果不準(zhǔn)確之處,希望各位讀者幫忙指正

          歡迎訪問?https://github.com/dtm-labs/dtm?并star支持我們


          想要了解更多 Golang 相關(guān)的內(nèi)容,歡迎掃描下方???關(guān)注?公眾號,回復(fù)關(guān)鍵詞 [實(shí)戰(zhàn)群]? ,就有機(jī)會進(jìn)群和我們進(jìn)行交流~


          瀏覽 41
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本乱伦精品 | 亚洲三高青在线观看免费 | 99热国产在线观看 | 日韩小电影 | 青青草在线视频网站 |