www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]這篇文章先介紹單機(jī)數(shù)據(jù)庫(kù)事務(wù)的ACID特性,然后指出分布式場(chǎng)景下操作多數(shù)據(jù)源面臨的困境,引出分布式系統(tǒng)中常用的分布式事務(wù)解決方案,這些解決方案可以保證業(yè)務(wù)代碼在操作多個(gè)數(shù)據(jù)源的時(shí)候,能夠像操作單個(gè)數(shù)據(jù)源一樣,具備ACID特性。

本文提綱如下


  • 0. 前言

  • 1. 單數(shù)據(jù)源事務(wù) & 多數(shù)據(jù)源事務(wù)

  • 2. 常見(jiàn)分布式事務(wù)解決方案

    • 2.1. 分布式事務(wù)模型

    • 2.2. 二將軍問(wèn)題和冪等性

    • 2.3. 兩階段提交(2PC) & 三階段提交(3PC)方案

    • 2.4. TCC 方案

    • 2.5. 事務(wù)狀態(tài)表方案

    • 2.6. 基于消息中間件的最終一致性事務(wù)方案

  • 3. Seata in AT mode 的實(shí)現(xiàn)

    • 3.1. Seata in AT mode 工作流程概述

    • 3.2. Seata in AT mode 工作流程詳述

  • 4. 結(jié)束語(yǔ)



1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

0. 前言

從 CPU 到內(nèi)存、到磁盤(pán)、到操作系統(tǒng)、到網(wǎng)絡(luò),計(jì)算機(jī)系統(tǒng)處處存在不可靠因素。工程師和科學(xué)家努力使用各種軟硬件方法對(duì)抗這種不可靠因素,保證數(shù)據(jù)和指令被正確地處理。在網(wǎng)絡(luò)領(lǐng)域有 TCP 可靠傳輸協(xié)議、在存儲(chǔ)領(lǐng)域有 Raid5 和 Raid6 算法、在數(shù)據(jù)庫(kù)領(lǐng)域有基于 ARIES 算法理論實(shí)現(xiàn)的事務(wù)機(jī)制……

這篇文章先介紹單機(jī)數(shù)據(jù)庫(kù)事務(wù)的 ACID 特性,然后指出分布式場(chǎng)景下操作多數(shù)據(jù)源面臨的困境,引出分布式系統(tǒng)中常用的分布式事務(wù)解決方案,這些解決方案可以保證業(yè)務(wù)代碼在操作多個(gè)數(shù)據(jù)源的時(shí)候,能夠像操作單個(gè)數(shù)據(jù)源一樣,具備 ACID 特性。文章在最后給出業(yè)界較為成熟的分布式事務(wù)框架——Seata 的 AT 模式全局事務(wù)的實(shí)現(xiàn)。

1. 單數(shù)據(jù)源事務(wù) & 多數(shù)據(jù)源事務(wù)

如果一個(gè)應(yīng)用程序在一次業(yè)務(wù)流中通過(guò)連接驅(qū)動(dòng)和數(shù)據(jù)源接口只連接并查詢(這里的查詢是廣義的,包括增刪查改等)一個(gè)特定的數(shù)據(jù)庫(kù),該應(yīng)用程序就可以利用數(shù)據(jù)庫(kù)提供的事務(wù)機(jī)制(如果數(shù)據(jù)庫(kù)支持事務(wù)的話)保證對(duì)庫(kù)中記錄所進(jìn)行的操作的可靠性,這里的可靠性有四種語(yǔ)義:

- 原子性,A

- 一致性,C

- 隔離性,I

- 持久性,D

筆者在這里不再對(duì)這四種語(yǔ)義進(jìn)行解釋?zhuān)私鈫螖?shù)據(jù)源事務(wù)及其 ACID 特性是讀者閱讀這篇文章的前提。單個(gè)數(shù)據(jù)庫(kù)實(shí)現(xiàn)自身的事務(wù)特性是一個(gè)復(fù)雜又微妙的過(guò)程,例如 MySQL 的 InnoDB 引擎通過(guò) Undo Log + Redo Log + ARIES 算法來(lái)實(shí)現(xiàn)。這是一個(gè)很宏大的話題,不在本文的描述范圍,讀者有興趣的話可自行研究。

單數(shù)據(jù)源事務(wù)也可以叫做單機(jī)事務(wù),或者本地事務(wù)。

在分布式場(chǎng)景下,一個(gè)系統(tǒng)由多個(gè)子系統(tǒng)構(gòu)成,每個(gè)子系統(tǒng)有獨(dú)立的數(shù)據(jù)源。多個(gè)子系統(tǒng)之間通過(guò)互相調(diào)用來(lái)組合出更復(fù)雜的業(yè)務(wù)。在時(shí)下流行的微服務(wù)系統(tǒng)架構(gòu)中,每一個(gè)子系統(tǒng)被稱(chēng)作一個(gè)微服務(wù),同樣每個(gè)微服務(wù)都維護(hù)自己的數(shù)據(jù)庫(kù),以保持獨(dú)立性。

例如,一個(gè)電商系統(tǒng)可能由購(gòu)物微服務(wù)、庫(kù)存微服務(wù)、訂單微服務(wù)等組成。購(gòu)物微服務(wù)通過(guò)調(diào)用庫(kù)存微服務(wù)和訂單微服務(wù)來(lái)整合出購(gòu)物業(yè)務(wù)。用戶請(qǐng)求購(gòu)物微服務(wù)商完成下單時(shí),購(gòu)物微服務(wù)一方面調(diào)用庫(kù)存微服務(wù)扣減相應(yīng)商品的庫(kù)存數(shù)量,另一方面調(diào)用訂單微服務(wù)插入訂單記錄(為了后文描述分布式事務(wù)解決方案的方便,這里給出的是一個(gè)最簡(jiǎn)單的電商系統(tǒng)微服務(wù)劃分和最簡(jiǎn)單的購(gòu)物業(yè)務(wù)流程,后續(xù)的支付、物流等業(yè)務(wù)不在考慮范圍內(nèi))。電商系統(tǒng)模型如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

在用戶購(gòu)物的業(yè)務(wù)場(chǎng)景中,shopping-service 的業(yè)務(wù)涉及兩個(gè)數(shù)據(jù)庫(kù):庫(kù)存庫(kù)(repo_db)和訂單庫(kù)(repo_db),也就是 g 購(gòu)物業(yè)務(wù)是調(diào)用多數(shù)據(jù)源來(lái)組合而成的。作為一個(gè)面向消費(fèi)者的系統(tǒng),電商系統(tǒng)要保證購(gòu)物業(yè)務(wù)的高度可靠性,這里的可靠性同樣有 ACID 四種語(yǔ)義。

但是一個(gè)數(shù)據(jù)庫(kù)的本地事務(wù)機(jī)制僅僅對(duì)落到自己身上的查詢操作(這里的查詢是廣義的,包括增刪改查等)起作用,無(wú)法干涉對(duì)其他數(shù)據(jù)庫(kù)的查詢操作。所以,數(shù)據(jù)庫(kù)自身提供的本地事務(wù)機(jī)制無(wú)法確保業(yè)務(wù)對(duì)多數(shù)據(jù)源全局操作的可靠性。

基于此,針對(duì)多數(shù)據(jù)源操作提出的分布式事務(wù)機(jī)制就出現(xiàn)了。

分布式事務(wù)也可以叫做全局事務(wù)。

2. 常見(jiàn)分布式事務(wù)解決方案

2.1. 分布式事務(wù)模型

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

描述分布式事務(wù),常常會(huì)使用以下幾個(gè)名詞:

- 事務(wù)參與者:例如每個(gè)數(shù)據(jù)庫(kù)就是一個(gè)事務(wù)參與者

- 事務(wù)協(xié)調(diào)者:訪問(wèn)多個(gè)數(shù)據(jù)源的服務(wù)程序,例如 shopping-service 就是事務(wù)協(xié)調(diào)者

- 資源管理器(Resource Manager, RM):通常與事務(wù)參與者同義

- 事務(wù)管理器(Transaction Manager, TM):通常與事務(wù)協(xié)調(diào)者同義

在分布式事務(wù)模型中,一個(gè) TM 管理多個(gè) RM,即一個(gè)服務(wù)程序訪問(wèn)多個(gè)數(shù)據(jù)源;TM 是一個(gè)全局事務(wù)管理器,協(xié)調(diào)多方本地事務(wù)的進(jìn)度,使其共同提交或回滾,最終達(dá)成一種全局的 ACID 特性。

2.2. 二將軍問(wèn)題和冪等性

二將軍問(wèn)題是網(wǎng)絡(luò)領(lǐng)域的一個(gè)經(jīng)典問(wèn)題,用于表達(dá)計(jì)算機(jī)網(wǎng)絡(luò)中互聯(lián)協(xié)議設(shè)計(jì)的微妙性和復(fù)雜性。這里給出一個(gè)二將軍問(wèn)題的簡(jiǎn)化版本:

一支白軍被圍困在一個(gè)山谷中,山谷的左右兩側(cè)是藍(lán)軍。困在山谷中的白軍人數(shù)多于山谷兩側(cè)的任意一支藍(lán)軍,而少于兩支藍(lán)軍的之和。若一支藍(lán)軍對(duì)白軍單獨(dú)發(fā)起進(jìn)攻,則必?cái)o(wú)疑;但若兩支藍(lán)軍同時(shí)發(fā)起進(jìn)攻,則可取勝。兩只藍(lán)軍的總指揮位于山谷左側(cè),他希望兩支藍(lán)軍同時(shí)發(fā)起進(jìn)攻,這樣就要把命令傳到山谷右側(cè)的藍(lán)軍,以告知發(fā)起進(jìn)攻的具體時(shí)間。假設(shè)他們只能派遣士兵穿越白軍所在的山谷(唯一的通信信道)來(lái)傳遞消息,那么在穿越山谷時(shí),士兵有可能被俘虜。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

只有當(dāng)送信士兵成功往返后,總指揮才能確認(rèn)這場(chǎng)戰(zhàn)爭(zhēng)的勝利(上方圖)?,F(xiàn)在問(wèn)題來(lái)了,派遣出去送信的士兵沒(méi)有回來(lái),則左側(cè)藍(lán)軍中的總指揮能不能決定按命令中約定的時(shí)間發(fā)起進(jìn)攻?

答案是不確定,派遣出去送信的士兵沒(méi)有回來(lái),他可能遇到兩種狀況:

1)命令還沒(méi)送達(dá)就被俘虜了(中間圖),這時(shí)候右側(cè)藍(lán)軍根本不知道要何時(shí)進(jìn)攻;

2)命令送達(dá),但返回途中被俘虜了(下方圖),這時(shí)候右側(cè)藍(lán)軍知道要何時(shí)進(jìn)攻,但左側(cè)藍(lán)軍不知道右側(cè)藍(lán)軍是否知曉進(jìn)攻時(shí)間。

類(lèi)似的問(wèn)題在計(jì)算機(jī)網(wǎng)絡(luò)中普遍存在,例如發(fā)送者給接受者發(fā)送一個(gè) HTTP 請(qǐng)求,或者 MySQL 客戶端向 MySQL 服務(wù)器發(fā)送一條插入語(yǔ)句,然后超時(shí)了沒(méi)有得到響應(yīng)。請(qǐng)問(wèn)服務(wù)器是寫(xiě)入成功了還是失敗了?答案是不確定,有以下幾種情況:

1)可能請(qǐng)求由于網(wǎng)絡(luò)故障根本沒(méi)有送到服務(wù)器,因此寫(xiě)入失??;

2)可能服務(wù)器收到了,也寫(xiě)入成功了,但是向客戶端發(fā)送響應(yīng)前服務(wù)器宕機(jī)了;

3)可能服務(wù)器收到了,也寫(xiě)入成功了,也向客戶端發(fā)送了響應(yīng),但是由于網(wǎng)絡(luò)故障未送到客戶端。

無(wú)論哪種場(chǎng)景,在客戶端看來(lái)都是一樣的結(jié)果:它發(fā)出的請(qǐng)求沒(méi)有得到響應(yīng)。為了確保服務(wù)端成功寫(xiě)入數(shù)據(jù),客戶端只能重發(fā)請(qǐng)求,直至接收到服務(wù)端的響應(yīng)。

類(lèi)似的問(wèn)題問(wèn)題被稱(chēng)為網(wǎng)絡(luò)二將軍問(wèn)題。

網(wǎng)絡(luò)二將軍問(wèn)題的存在使得消息的發(fā)送者往往要重復(fù)發(fā)送消息,直到收到接收者的確認(rèn)才認(rèn)為發(fā)送成功,但這往往又會(huì)導(dǎo)致消息的重復(fù)發(fā)送。例如電商系統(tǒng)中訂單模塊調(diào)用支付模塊扣款的時(shí)候,如果網(wǎng)絡(luò)故障導(dǎo)致二將軍問(wèn)題出現(xiàn),扣款請(qǐng)求重復(fù)發(fā)送,產(chǎn)生的重復(fù)扣款結(jié)果顯然是不能被接受的。因此要保證一次事務(wù)中的扣款請(qǐng)求無(wú)論被發(fā)送多少次,接收方有且只執(zhí)行一次扣款動(dòng)作,這種保證機(jī)制叫做接收方的冪等性。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

2.3. 兩階段提交(2PC) & 三階段提交(3PC)方案

2PC 是一種實(shí)現(xiàn)分布式事務(wù)的簡(jiǎn)單模型,這兩個(gè)階段是:

1)準(zhǔn)備階段:事務(wù)協(xié)調(diào)者向各個(gè)事務(wù)參與者發(fā)起詢問(wèn)請(qǐng)求:“我要執(zhí)行全局事務(wù)了,這個(gè)事務(wù)涉及到的資源分布在你們這些數(shù)據(jù)源中,分別是……,你們準(zhǔn)備好各自的資源(即各自執(zhí)行本地事務(wù)到待提交階段)”。各個(gè)參與者協(xié)調(diào)者回復(fù) yes(表示已準(zhǔn)備好,允許提交全局事務(wù))或 no(表示本參與者無(wú)法拿到全局事務(wù)所需的本地資源,因?yàn)樗黄渌镜厥聞?wù)鎖住了)或超時(shí)。

2)提交階段:如果各個(gè)參與者回復(fù)的都是 yes,則協(xié)調(diào)者向所有參與者發(fā)起事務(wù)提交操作,然后所有參與者收到后各自執(zhí)行本地事務(wù)提交操作并向協(xié)調(diào)者發(fā)送 ACK;如果任何一個(gè)參與者回復(fù) no 或者超時(shí),則協(xié)調(diào)者向所有參與者發(fā)起事務(wù)回滾操作,然后所有參與者收到后各自執(zhí)行本地事務(wù)回滾操作并向協(xié)調(diào)者發(fā)送 ACK。

2PC 的流程如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

從上圖可以看出,要實(shí)現(xiàn) 2PC,所有的參與者都要實(shí)現(xiàn)三個(gè)接口:

  • Prepare():TM 調(diào)用該接口詢問(wèn)各個(gè)本地事務(wù)是否就緒

  • Commit():TM 調(diào)用該接口要求各個(gè)本地事務(wù)提交

  • Rollback():TM 調(diào)用該接口要求各個(gè)本地事務(wù)回滾

可以將這三個(gè)接口簡(jiǎn)單地(但不嚴(yán)謹(jǐn)?shù)兀├斫獬?XA 協(xié)議。XA 協(xié)議是 X/Open 提出的分布式事務(wù)處理標(biāo)準(zhǔn)。MySQL、Oracle、DB2 這些主流數(shù)據(jù)庫(kù)都實(shí)現(xiàn)了 XA 協(xié)議,因此都能被用于實(shí)現(xiàn) 2PC 事務(wù)模型。

2PC 簡(jiǎn)明易懂,但存在如下的問(wèn)題:

1)性能差,在準(zhǔn)備階段,要等待所有的參與者返回,才能進(jìn)入階段二,在這期間,各個(gè)參與者上面的相關(guān)資源被排他地鎖住,參與者上面意圖使用這些資源的本地事務(wù)只能等待。因?yàn)榇嬖谶@種同步阻塞問(wèn)題,所以影響了各個(gè)參與者的本地事務(wù)并發(fā)度;

2)準(zhǔn)備階段完成后,如果協(xié)調(diào)者宕機(jī),所有的參與者都收不到提交或回滾指令,導(dǎo)致所有參與者“不知所措”;

3)在提交階段,協(xié)調(diào)者向所有的參與者發(fā)送了提交指令,如果一個(gè)參與者未返回 ACK,那么協(xié)調(diào)者不知道這個(gè)參與者內(nèi)部發(fā)生了什么(由于網(wǎng)絡(luò)二將軍問(wèn)題的存在,這個(gè)參與者可能根本沒(méi)收到提交指令,一直處于等待接收提交指令的狀態(tài);也可能收到了,并成功執(zhí)行了本地提交,但返回的 ACK 由于網(wǎng)絡(luò)故障未送到協(xié)調(diào)者上),也就無(wú)法決定下一步是否進(jìn)行全體參與者的回滾。

2PC 之后又出現(xiàn)了 3PC,把兩階段過(guò)程變成了三階段過(guò)程,分別是:詢問(wèn)階段、準(zhǔn)備階段、提交或回滾階段,這里不再詳述。3PC 利用超時(shí)機(jī)制解決了 2PC 的同步阻塞問(wèn)題,避免資源被永久鎖定,進(jìn)一步加強(qiáng)了整個(gè)事務(wù)過(guò)程的可靠性。但是 3PC 同樣無(wú)法應(yīng)對(duì)類(lèi)似的宕機(jī)問(wèn)題,只不過(guò)出現(xiàn)多數(shù)據(jù)源中數(shù)據(jù)不一致問(wèn)題的概率更小。

2PC 除了性能和可靠性上存在問(wèn)題,它的適用場(chǎng)景也很局限,它要求參與者實(shí)現(xiàn)了 XA 協(xié)議,例如使用實(shí)現(xiàn)了 XA 協(xié)議的數(shù)據(jù)庫(kù)作為參與者可以完成 2PC 過(guò)程。但是在多個(gè)系統(tǒng)服務(wù)利用 api 接口相互調(diào)用的時(shí)候,就不遵守 XA 協(xié)議了,這時(shí)候 2PC 就不適用了。所以 2PC 在分布式應(yīng)用場(chǎng)景中很少使用。

所以前文提到的電商場(chǎng)景無(wú)法使用 2PC,因?yàn)?shopping-service 通過(guò) RPC 接口或者 Rest 接口調(diào)用 repo-service 和 order-service 間接訪問(wèn) repo_db 和 order_db。除非 shopping-service 直接配置 repo_db 和 order_db 作為自己的數(shù)據(jù)庫(kù)。

2.4. TCC 方案

描述 TCC 方案使用的電商微服務(wù)模型如下圖所示,在這個(gè)模型中,shopping-service 是事務(wù)協(xié)調(diào)者,repo-service 和 order-service 是事務(wù)參與者。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

上文提到,2PC 要求參與者實(shí)現(xiàn)了 XA 協(xié)議,通常用來(lái)解決多個(gè)數(shù)據(jù)庫(kù)之間的事務(wù)問(wèn)題,比較局限。在多個(gè)系統(tǒng)服務(wù)利用 api 接口相互調(diào)用的時(shí)候,就不遵守 XA 協(xié)議了,這時(shí)候 2PC 就不適用了?,F(xiàn)代企業(yè)多采用分布式的微服務(wù),因此更多的是要解決多個(gè)微服務(wù)之間的分布式事務(wù)問(wèn)題。

TCC 就是一種解決多個(gè)微服務(wù)之間的分布式事務(wù)問(wèn)題的方案。TCC 是 Try、Confirm、Cancel 三個(gè)詞的縮寫(xiě),其本質(zhì)是一個(gè)應(yīng)用層面上的 2PC,同樣分為兩個(gè)階段:

1)階段一:準(zhǔn)備階段。協(xié)調(diào)者調(diào)用所有的每個(gè)微服務(wù)提供的 try 接口,將整個(gè)全局事務(wù)涉及到的資源鎖定住,若鎖定成功 try 接口向協(xié)調(diào)者返回 yes。

2)階段二:提交階段。若所有的服務(wù)的 try 接口在階段一都返回 yes,則進(jìn)入提交階段,協(xié)調(diào)者調(diào)用所有服務(wù)的 confirm 接口,各個(gè)服務(wù)進(jìn)行事務(wù)提交。如果有任何一個(gè)服務(wù)的 try 接口在階段一返回 no 或者超時(shí),則協(xié)調(diào)者調(diào)用所有服務(wù)的 cancel 接口。

TCC 的流程如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

這里有個(gè)關(guān)鍵問(wèn)題,既然 TCC 是一種服務(wù)層面上的 2PC,它是如何解決 2PC 無(wú)法應(yīng)對(duì)宕機(jī)問(wèn)題的缺陷的呢?答案是不斷重試。由于 try 操作鎖住了全局事務(wù)涉及的所有資源,保證了業(yè)務(wù)操作的所有前置條件得到滿足,因此無(wú)論是 confirm 階段失敗還是 cancel 階段失敗都能通過(guò)不斷重試直至 confirm 或 cancel 成功(所謂成功就是所有的服務(wù)都對(duì) confirm 或者 cancel 返回了 ACK)。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

這里還有個(gè)關(guān)鍵問(wèn)題,在不斷重試 confirm 和 cancel 的過(guò)程中(考慮到網(wǎng)絡(luò)二將軍問(wèn)題的存在)有可能重復(fù)進(jìn)行了 confirm 或 cancel,因此還要再保證 confirm 和 cancel 操作具有冪等性,也就是整個(gè)全局事務(wù)中,每個(gè)參與者只進(jìn)行一次 confirm 或者 cancel。實(shí)現(xiàn) confirm 和 cancel 操作的冪等性,有很多解決方案,例如每個(gè)參與者可以維護(hù)一個(gè)去重表(可以利用數(shù)據(jù)庫(kù)表實(shí)現(xiàn)也可以使用內(nèi)存型 KV 組件實(shí)現(xiàn)),記錄每個(gè)全局事務(wù)(以全局事務(wù)標(biāo)記 XID 區(qū)分)是否進(jìn)行過(guò) confirm 或 cancel 操作,若已經(jīng)進(jìn)行過(guò),則不再重復(fù)執(zhí)行。

TCC 由支付寶團(tuán)隊(duì)提出,被廣泛應(yīng)用于金融系統(tǒng)中。我們用銀行賬戶余額購(gòu)買(mǎi)基金時(shí),會(huì)注意到銀行賬戶中用于購(gòu)買(mǎi)基金的那部分余額首先會(huì)被凍結(jié),由此我們可以猜想,這個(gè)過(guò)程大概就是 TCC 的第一階段。

2.5. 事務(wù)狀態(tài)表方案

另外有一種類(lèi)似 TCC 的事務(wù)解決方案,借助事務(wù)狀態(tài)表來(lái)實(shí)現(xiàn)。假設(shè)要在一個(gè)分布式事務(wù)中實(shí)現(xiàn)調(diào)用 repo-service 扣減庫(kù)存、調(diào)用 order-service 生成訂單兩個(gè)過(guò)程。在這種方案中,協(xié)調(diào)者 shopping-service 維護(hù)一張如下的事務(wù)狀態(tài)表:

分布式事務(wù) ID 事務(wù)內(nèi)容 事務(wù)狀態(tài)
global_trx_id_1 操作 1:調(diào)用 repo-service 扣減庫(kù)存
操作 2:調(diào)用 order-service 生成訂單
狀態(tài) 1:初始
狀態(tài) 2:操作 1 成功
狀態(tài) 3:操作 1、2 成功

初始狀態(tài)為 1,每成功調(diào)用一個(gè)服務(wù)則更新一次狀態(tài),最后所有的服務(wù)調(diào)用成功,狀態(tài)更新到 3。

有了這張表,就可以啟動(dòng)一個(gè)后臺(tái)任務(wù),掃描這張表中事務(wù)的狀態(tài),如果一個(gè)分布式事務(wù)一直(設(shè)置一個(gè)事務(wù)周期閾值)未到狀態(tài) 3,說(shuō)明這條事務(wù)沒(méi)有成功執(zhí)行,于是可以重新調(diào)用 repo-service 扣減庫(kù)存、調(diào)用 order-service 生成訂單。直至所有的調(diào)用成功,事務(wù)狀態(tài)到 3。

如果多次重試仍未使得狀態(tài)到 3,可以將事務(wù)狀態(tài)置為 error,通過(guò)人工介入進(jìn)行干預(yù)。

由于存在服務(wù)的調(diào)用重試,因此每個(gè)服務(wù)的接口要根據(jù)全局的分布式事務(wù) ID 做冪等,原理同 2.4 節(jié)的冪等性實(shí)現(xiàn)。

2.6. 基于消息中間件的最終一致性事務(wù)方案

無(wú)論是 2PC & 3PC 還是 TCC、事務(wù)狀態(tài)表,基本都遵守 XA 協(xié)議的思想,即這些方案本質(zhì)上都是事務(wù)協(xié)調(diào)者協(xié)調(diào)各個(gè)事務(wù)參與者的本地事務(wù)的進(jìn)度,使所有本地事務(wù)共同提交或回滾,最終達(dá)成一種全局的 ACID 特性。在協(xié)調(diào)的過(guò)程中,協(xié)調(diào)者需要收集各個(gè)本地事務(wù)的當(dāng)前狀態(tài),并根據(jù)這些狀態(tài)發(fā)出下一階段的操作指令。

但是這些全局事務(wù)方案由于操作繁瑣、時(shí)間跨度大,或者在全局事務(wù)期間會(huì)排他地鎖住相關(guān)資源,使得整個(gè)分布式系統(tǒng)的全局事務(wù)的并發(fā)度不會(huì)太高。這很難滿足電商等高并發(fā)場(chǎng)景對(duì)事務(wù)吞吐量的要求,因此互聯(lián)網(wǎng)服務(wù)提供商探索出了很多與 XA 協(xié)議背道而馳的分布式事務(wù)解決方案。其中利用消息中間件實(shí)現(xiàn)的最終一致性全局事務(wù)就是一個(gè)經(jīng)典方案。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

為了表現(xiàn)出這種方案的精髓,我將使用如下的電商系統(tǒng)微服務(wù)結(jié)構(gòu)來(lái)進(jìn)行描述:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

在這個(gè)模型中,用戶不再是請(qǐng)求整合后的 shopping-service 進(jìn)行下單,而是直接請(qǐng)求 order-service 下單,order-service 一方面添加訂單記錄,另一方面會(huì)調(diào)用 repo-service 扣減庫(kù)存。

這種基于消息中間件的最終一致性事務(wù)方案常常被誤解成如下的實(shí)現(xiàn)方式:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

這種實(shí)現(xiàn)方式的流程是:

1)order-service 負(fù)責(zé)向 MQ server 發(fā)送扣減庫(kù)存消息(repo_deduction_msg);repo-service 訂閱 MQ server 中的扣減庫(kù)存消息,負(fù)責(zé)消費(fèi)消息。

2)用戶下單后,order-service 先執(zhí)行插入訂單記錄的查詢語(yǔ)句,后將 repo_deduction_msg 發(fā)到消息中間件中,這兩個(gè)過(guò)程放在一個(gè)本地事務(wù)中進(jìn)行,一旦“執(zhí)行插入訂單記錄的查詢語(yǔ)句”失敗,導(dǎo)致事務(wù)回滾,“將 repo_deduction_msg 發(fā)到消息中間件中”就不會(huì)發(fā)生;同樣,一旦“將 repo_deduction_msg 發(fā)到消息中間件中”失敗,拋出異常,也會(huì)導(dǎo)致“執(zhí)行插入訂單記錄的查詢語(yǔ)句”操作回滾,最終什么也沒(méi)有發(fā)生。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

3)repo-service 接收到 repo_deduction_msg 之后,先執(zhí)行庫(kù)存扣減查詢語(yǔ)句,后向 MQ sever 反饋消息消費(fèi)完成 ACK,這兩個(gè)過(guò)程放在一個(gè)本地事務(wù)中進(jìn)行,一旦“執(zhí)行庫(kù)存扣減查詢語(yǔ)句”失敗,導(dǎo)致事務(wù)回滾,“向 MQ sever 反饋消息消費(fèi)完成 ACK”就不會(huì)發(fā)生,MQ server 在 Confirm 機(jī)制的驅(qū)動(dòng)下會(huì)繼續(xù)向 repo-service 推送該消息,直到整個(gè)事務(wù)成功提交;同樣,一旦“向 MQ sever 反饋消息消費(fèi)完成 ACK”失敗,拋出異常,也對(duì)導(dǎo)致“執(zhí)行庫(kù)存扣減查詢語(yǔ)句”操作回滾,MQ server 在 Confirm 機(jī)制的驅(qū)動(dòng)下會(huì)繼續(xù)向 repo-service 推送該消息,直到整個(gè)事務(wù)成功提交。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

這種做法看似很可靠。但沒(méi)有考慮到網(wǎng)絡(luò)二將軍問(wèn)題的存在,有如下的缺陷:

1)存在網(wǎng)絡(luò)的 2 將軍問(wèn)題,上面第 2)步中 order-service 發(fā)送 repo_deduction_msg 消息失敗,對(duì)于發(fā)送方 order-service 來(lái)說(shuō),可能是消息中間件沒(méi)有收到消息;也可能是中間件收到了消息,但向發(fā)送方 order-service 響應(yīng)的 ACK 由于網(wǎng)絡(luò)故障沒(méi)有被 order-service 收到。因此 order-service 貿(mào)然進(jìn)行事務(wù)回滾,撤銷(xiāo)“執(zhí)行插入訂單記錄的查詢語(yǔ)句”,是不對(duì)的,因?yàn)?repo-service 那邊可能已經(jīng)接收到 repo_deduction_msg 并成功進(jìn)行了庫(kù)存扣減,這樣 order-service 和 repo-service 兩方就產(chǎn)生了數(shù)據(jù)不一致問(wèn)題。

2)repo-service 和 order-service 把網(wǎng)絡(luò)調(diào)用(與 MQ server 通信)放在本地?cái)?shù)據(jù)庫(kù)事務(wù)里,可能會(huì)因?yàn)榫W(wǎng)絡(luò)延遲產(chǎn)生數(shù)據(jù)庫(kù)長(zhǎng)事務(wù),影響數(shù)據(jù)庫(kù)本地事務(wù)的并發(fā)度。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理
015

以上是被誤解的實(shí)現(xiàn)方式,下面給出正確的實(shí)現(xiàn)方式,如下所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

上圖所示的方案,利用消息中間件如 rabbitMQ 來(lái)實(shí)現(xiàn)分布式下單及庫(kù)存扣減過(guò)程的最終一致性。對(duì)這幅圖做以下說(shuō)明:

1)order-service 中,


在?t_order?表添加訂單記錄?&&

在?t_local_msg?添加對(duì)應(yīng)的扣減庫(kù)存消息

這兩個(gè)過(guò)程要在一個(gè)事務(wù)中完成,保證過(guò)程的原子性。同樣,repo-service 中,


檢查本次扣庫(kù)存操作是否已經(jīng)執(zhí)行過(guò)?&&

執(zhí)行扣減庫(kù)存如果本次扣減操作沒(méi)有執(zhí)行過(guò)?&&

寫(xiě)判重表?&&

向?MQ?sever?反饋消息消費(fèi)完成?ACK

這四個(gè)過(guò)程也要在一個(gè)事務(wù)中完成,保證過(guò)程的原子性。

2)order-service 中有一個(gè)后臺(tái)程序,源源不斷地把消息表中的消息傳送給消息中間件,成功后則刪除消息表中對(duì)應(yīng)的消息。如果失敗了,也會(huì)不斷嘗試重傳。由于存在網(wǎng)絡(luò) 2 將軍問(wèn)題,即當(dāng) order-service 發(fā)送給消息中間件的消息網(wǎng)絡(luò)超時(shí)時(shí),這時(shí)候消息中間件可能收到了消息但響應(yīng) ACK 失敗,也可能沒(méi)收到,order-service 會(huì)再次發(fā)送該消息,直至消息中間件響應(yīng) ACK 成功,這樣可能發(fā)生消息的重復(fù)發(fā)送,不過(guò)沒(méi)關(guān)系,只要保證消息不丟失,不亂序就行,后面 repo-service 會(huì)做去重處理。

3)消息中間件向 repo-service 推送 repo_deduction_msg,repo-service 成功處理完成后會(huì)向中間件響應(yīng) ACK,消息中間件收到這個(gè) ACK 才認(rèn)為 repo-service 成功處理了這條消息,否則會(huì)重復(fù)推送該消息。但是有這樣的情形:repo-service 成功處理了消息,向中間件發(fā)送的 ACK 在網(wǎng)絡(luò)傳輸中由于網(wǎng)絡(luò)故障丟失了,導(dǎo)致中間件沒(méi)有收到 ACK 重新推送了該消息。這也要靠 repo-service 的消息去重特性來(lái)避免消息重復(fù)消費(fèi)。

4)在 2)和 3)中提到了兩種導(dǎo)致 repo-service 重復(fù)收到消息的原因,一是生產(chǎn)者重復(fù)生產(chǎn),二是中間件重傳。為了實(shí)現(xiàn)業(yè)務(wù)的冪等性,repo-service 中維護(hù)了一張判重表,這張表中記錄了被成功處理的消息的 id。repo-service 每次接收到新的消息都先判斷消息是否被成功處理過(guò),若是的話不再重復(fù)處理。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

通過(guò)這種設(shè)計(jì),實(shí)現(xiàn)了消息在發(fā)送方不丟失,消息在接收方不被重復(fù)消費(fèi),聯(lián)合起來(lái)就是消息不漏不重,嚴(yán)格實(shí)現(xiàn)了 order-service 和 repo-service 的兩個(gè)數(shù)據(jù)庫(kù)中數(shù)據(jù)的最終一致性。

基于消息中間件的最終一致性全局事務(wù)方案是互聯(lián)網(wǎng)公司在高并發(fā)場(chǎng)景中探索出的一種創(chuàng)新型應(yīng)用模式,利用 MQ 實(shí)現(xiàn)微服務(wù)之間的異步調(diào)用、解耦合和流量削峰,支持全局事務(wù)的高并發(fā),并保證分布式數(shù)據(jù)記錄的最終一致性。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

3. Seata in AT mode 的實(shí)現(xiàn)

第 2 章給出了實(shí)現(xiàn)實(shí)現(xiàn)分布式事務(wù)的集中常見(jiàn)的理論模型。本章給出業(yè)界開(kāi)源分布式事務(wù)框架 Seata 的實(shí)現(xiàn)。

Seata 為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式。其中 AT 模式是 Seata 主推的事務(wù)模式,因此本章分析 Seata in AT mode 的實(shí)現(xiàn)。使用 AT 有一個(gè)前提,那就是微服務(wù)使用的數(shù)據(jù)庫(kù)必須是支持事務(wù)的關(guān)系型數(shù)據(jù)庫(kù)。

3.1. Seata in AT mode 工作流程概述

Seata 的 AT 模式建立在關(guān)系型數(shù)據(jù)庫(kù)的本地事務(wù)特性的基礎(chǔ)之上,通過(guò)數(shù)據(jù)源代理類(lèi)攔截并解析數(shù)據(jù)庫(kù)執(zhí)行的 SQL,記錄自定義的回滾日志,如需回滾,則重放這些自定義的回滾日志即可。AT 模式雖然是根據(jù) XA 事務(wù)模型(2PC)演進(jìn)而來(lái)的,但是 AT 打破了 XA 協(xié)議的阻塞性制約,在一致性和性能上取得了平衡。

AT 模式是基于 XA 事務(wù)模型演進(jìn)而來(lái)的,它的整體機(jī)制也是一個(gè)改進(jìn)版本的兩階段提交協(xié)議。AT 模式的兩個(gè)基本階段是:

1)第一階段:首先獲取本地鎖,執(zhí)行本地事務(wù),業(yè)務(wù)數(shù)據(jù)操作和記錄回滾日志在同一個(gè)本地事務(wù)中提交,最后釋放本地鎖;

2)第二階段:如需全局提交,異步刪除回滾日志即可,這個(gè)過(guò)程很快就能完成。如需要回滾,則通過(guò)第一階段的回滾日志進(jìn)行反向補(bǔ)償。

本章描述 Seata in AT mode 的工作原理使用的電商微服務(wù)模型如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

在上圖中,協(xié)調(diào)者 shopping-service 先調(diào)用參與者 repo-service 扣減庫(kù)存,后調(diào)用參與者 order-service 生成訂單。這個(gè)業(yè)務(wù)流使用 Seata in XA mode 后的全局事務(wù)流程如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

上圖描述的全局事務(wù)執(zhí)行流程為:

1)shopping-service 向 Seata 注冊(cè)全局事務(wù),并產(chǎn)生一個(gè)全局事務(wù)標(biāo)識(shí) XID

2)將 repo-service.repo_db、order-service.order_db 的本地事務(wù)執(zhí)行到待提交階段,事務(wù)內(nèi)容包含對(duì) repo-service.repo_db、order-service.order_db 進(jìn)行的查詢操作以及寫(xiě)每個(gè)庫(kù)的 undo_log 記錄

3)repo-service.repo_db、order-service.order_db 向 Seata 注冊(cè)分支事務(wù),并將其納入該 XID 對(duì)應(yīng)的全局事務(wù)范圍

4)提交 repo-service.repo_db、order-service.order_db 的本地事務(wù)

5)repo-service.repo_db、order-service.order_db 向 Seata 匯報(bào)分支事務(wù)的提交狀態(tài)

6)Seata 匯總所有的 DB 的分支事務(wù)的提交狀態(tài),決定全局事務(wù)是該提交還是回滾

7)Seata 通知 repo-service.repo_db、order-service.order_db 提交/回滾本地事務(wù),若需要回滾,采取的是補(bǔ)償式方法

其中 1)2)3)4)5)屬于第一階段,6)7)屬于第二階段。

3.2. Seata in AT mode 工作流程詳述

在上面的電商業(yè)務(wù)場(chǎng)景中,購(gòu)物服務(wù)調(diào)用庫(kù)存服務(wù)扣減庫(kù)存,調(diào)用訂單服務(wù)創(chuàng)建訂單,顯然這兩個(gè)調(diào)用過(guò)程要放在一個(gè)事務(wù)里面。即:


start?global_trx

?call?庫(kù)存服務(wù)的扣減庫(kù)存接口

?call?訂單服務(wù)的創(chuàng)建訂單接口

commit?global_trx

在庫(kù)存服務(wù)的數(shù)據(jù)庫(kù)中,存在如下的庫(kù)存表 t_repo:

id production_code name count price
10001 20001 xx 鍵盤(pán) 98 200.0
10002 20002 yy 鼠標(biāo) 199 100.0

在訂單服務(wù)的數(shù)據(jù)庫(kù)中,存在如下的訂單表 t_order:

id order_code user_id production_code count price
30001 2020102500001 40001 20002 1 100.0
30002 2020102500001 40001 20001 2 400.0

現(xiàn)在,id 為 40002 的用戶要購(gòu)買(mǎi)一只商品代碼為 20002 的鼠標(biāo),整個(gè)分布式事務(wù)的內(nèi)容為:

1)在庫(kù)存服務(wù)的庫(kù)存表中將記錄

id production_code name count price
10002 20002 yy 鼠標(biāo) 199 100.0

修改為

id production_code name count price
10002 20002 yy 鼠標(biāo) 198 100.0

2)在訂單服務(wù)的訂單表中添加一條記錄

id order_code user_id production_code count price
30003 2020102500002 40002 20002 1 100.0

以上操作,在 AT 模式的第一階段的流程圖如下:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

從 AT 模式第一階段的流程來(lái)看,分支的本地事務(wù)在第一階段提交完成之后,就會(huì)釋放掉本地事務(wù)鎖定的本地記錄。這是 AT 模式和 XA 最大的不同點(diǎn),在 XA 事務(wù)的兩階段提交中,被鎖定的記錄直到第二階段結(jié)束才會(huì)被釋放。所以 AT 模式減少了鎖記錄的時(shí)間,從而提高了分布式事務(wù)的處理效率。AT 模式之所以能夠?qū)崿F(xiàn)第一階段完成就釋放被鎖定的記錄,是因?yàn)?Seata 在每個(gè)服務(wù)的數(shù)據(jù)庫(kù)中維護(hù)了一張 undo_log 表,其中記錄了對(duì) t_order / t_repo 進(jìn)行操作前后記錄的鏡像數(shù)據(jù),即便第二階段發(fā)生異常,只需回放每個(gè)服務(wù)的 undo_log 中的相應(yīng)記錄即可實(shí)現(xiàn)全局回滾。

undo_log 的表結(jié)構(gòu):

id branch_id xid context rollback_info log_status log_created log_modified
…… 分支事務(wù) ID 全局事務(wù) ID …… 分支事務(wù)操作的記錄在事務(wù)前后的記錄鏡像,即 beforeImage 和 afterImage …… …… ……

第一階段結(jié)束之后,Seata 會(huì)接收到所有分支事務(wù)的提交狀態(tài),然后決定是提交全局事務(wù)還是回滾全局事務(wù)。

1)若所有分支事務(wù)本地提交均成功,則 Seata 決定全局提交。Seata 將分支提交的消息發(fā)送給各個(gè)分支事務(wù),各個(gè)分支事務(wù)收到分支提交消息后,會(huì)將消息放入一個(gè)緩沖隊(duì)列,然后直接向 Seata 返回提交成功。之后,每個(gè)本地事務(wù)會(huì)慢慢處理分支提交消息,處理的方式為:刪除相應(yīng)分支事務(wù)的 undo_log 記錄。之所以只需刪除分支事務(wù)的 undo_log 記錄,而不需要再做其他提交操作,是因?yàn)樘峤徊僮饕呀?jīng)在第一階段完成了(這也是 AT 和 XA 不同的地方)。這個(gè)過(guò)程如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

分支事務(wù)之所以能夠直接返回成功給 Seata,是因?yàn)檎嬲P(guān)鍵的提交操作在第一階段已經(jīng)完成了,清除 undo_log 日志只是收尾工作,即便清除失敗了,也對(duì)整個(gè)分布式事務(wù)不產(chǎn)生實(shí)質(zhì)影響。

2)若任一分支事務(wù)本地提交失敗,則 Seata 決定全局回滾,將分支事務(wù)回滾消息發(fā)送給各個(gè)分支事務(wù),由于在第一階段各個(gè)服務(wù)的數(shù)據(jù)庫(kù)上記錄了 undo_log 記錄,分支事務(wù)回滾操作只需根據(jù) undo_log 記錄進(jìn)行補(bǔ)償即可。全局事務(wù)的回滾流程如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

這里對(duì)圖中的 2、3 步做進(jìn)一步的說(shuō)明:

1)由于上文給出了 undo_log 的表結(jié)構(gòu),所以可以通過(guò) xid 和 branch_id 來(lái)找到當(dāng)前分支事務(wù)的所有 undo_log 記錄;

2)拿到當(dāng)前分支事務(wù)的 undo_log 記錄之后,首先要做數(shù)據(jù)校驗(yàn),如果 afterImage 中的記錄與當(dāng)前的表記錄不一致,說(shuō)明從第一階段完成到此刻期間,有別的事務(wù)修改了這些記錄,這會(huì)導(dǎo)致分支事務(wù)無(wú)法回滾,向 Seata 反饋回滾失?。蝗绻?afterImage 中的記錄與當(dāng)前的表記錄一致,說(shuō)明從第一階段完成到此刻期間,沒(méi)有別的事務(wù)修改這些記錄,分支事務(wù)可回滾,進(jìn)而根據(jù) beforeImage 和 afterImage 計(jì)算出補(bǔ)償 SQL,執(zhí)行補(bǔ)償 SQL 進(jìn)行回滾,然后刪除相應(yīng) undo_log,向 Seata 反饋回滾成功。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

事務(wù)具有 ACID 特性,全局事務(wù)解決方案也在盡量實(shí)現(xiàn)這四個(gè)特性。以上關(guān)于 Seata in AT mode 的描述很顯然體現(xiàn)出了 AT 的原子性、一致性和持久性。下面著重描述一下 AT 如何保證多個(gè)全局事務(wù)的隔離性的。

在 AT 中,當(dāng)多個(gè)全局事務(wù)操作同一張表時(shí),通過(guò)全局鎖來(lái)保證事務(wù)的隔離性。下面描述一下全局鎖在讀隔離和寫(xiě)隔離兩個(gè)場(chǎng)景中的作用原理:

1)寫(xiě)隔離(若有全局事務(wù)在改/寫(xiě)/刪記錄,另一個(gè)全局事務(wù)對(duì)同一記錄進(jìn)行的改/寫(xiě)/刪要被隔離起來(lái),即寫(xiě)寫(xiě)互斥):寫(xiě)隔離是為了在多個(gè)全局事務(wù)對(duì)同一張表的同一個(gè)字段進(jìn)行更新操作時(shí),避免一個(gè)全局事務(wù)在沒(méi)有被提交成功之前所涉及的數(shù)據(jù)被其他全局事務(wù)修改。寫(xiě)隔離的基本原理是:在第一階段本地事務(wù)(開(kāi)啟本地事務(wù)的時(shí)候,本地事務(wù)會(huì)對(duì)涉及到的記錄加本地鎖)提交之前,確保拿到全局鎖。如果拿不到全局鎖,就不能提交本地事務(wù),并且不斷嘗試獲取全局鎖,直至超出重試次數(shù),放棄獲取全局鎖,回滾本地事務(wù),釋放本地事務(wù)對(duì)記錄加的本地鎖。

假設(shè)有兩個(gè)全局事務(wù) gtrx_1 和 gtrx_2 在并發(fā)操作庫(kù)存服務(wù),意圖扣減如下記錄的庫(kù)存數(shù)量:

id production_code name count price
10002 20002 yy 鼠標(biāo) 198 100.0

AT 實(shí)現(xiàn)寫(xiě)隔離過(guò)程的時(shí)序圖如下:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

圖中,1、2、3、4 屬于第一階段,5 屬于第二階段。

在上圖中 gtrx_1 和 gtrx_2 均成功提交,如果 gtrx_1 在第二階段執(zhí)行回滾操作,那么 gtrx_1 需要重新發(fā)起本地事務(wù)獲取本地鎖,然后根據(jù) undo_log 對(duì)這個(gè) id=10002 的記錄進(jìn)行補(bǔ)償式回滾。此時(shí) gtrx_2 仍在等待全局鎖,且持有這個(gè) id=10002 的記錄的本地鎖,因此 gtrx_1 會(huì)回滾失?。╣trx_1 回滾需要同時(shí)持有全局鎖和對(duì) id=10002 的記錄加的本地鎖),回滾失敗的 gtrx_1 會(huì)一直重試回滾。直到旁邊的 gtrx_2 獲取全局鎖的嘗試次數(shù)超過(guò)閾值,gtrx_2 會(huì)放棄獲取全局鎖,發(fā)起本地回滾,本地回滾結(jié)束后,自然會(huì)釋放掉對(duì)這個(gè) id=10002 的記錄加的本地鎖。此時(shí),gtrx_1 終于可以成功對(duì)這個(gè) id=10002 的記錄加上了本地鎖,同時(shí)拿到了本地鎖和全局鎖的 gtrx_1 就可以成功回滾了。整個(gè)過(guò)程,全局鎖始終在 gtrx_1 手中,并不會(huì)發(fā)生臟寫(xiě)的問(wèn)題。整個(gè)過(guò)程的流程圖如下所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

2)讀隔離(若有全局事務(wù)在改/寫(xiě)/刪記錄,另一個(gè)全局事務(wù)對(duì)同一記錄的讀取要被隔離起來(lái),即讀寫(xiě)互斥):在數(shù)據(jù)庫(kù)本地事務(wù)的隔離級(jí)別為讀已提交、可重復(fù)讀、串行化時(shí)(讀未提交不起什么隔離作用,一般不使用),Seata AT 全局事務(wù)模型產(chǎn)生的隔離級(jí)別是讀未提交,也就是說(shuō)一個(gè)全局事務(wù)會(huì)看到另一個(gè)全局事務(wù)未全局提交的數(shù)據(jù),產(chǎn)生臟讀,從前文的第一階段和第二階段的流程圖中也可以看出這一點(diǎn)。這在最終一致性的分布式事務(wù)模型中是可以接受的。

如果要求 AT 模型一定要實(shí)現(xiàn)讀已提交的事務(wù)隔離級(jí)別,可以利用 Seata 的 SelectForUpdateExecutor 執(zhí)行器對(duì) SELECT FOR UPDATE 語(yǔ)句進(jìn)行代理。SELECT FOR UPDATE 語(yǔ)句在執(zhí)行時(shí)會(huì)申請(qǐng)全局鎖,如果全局鎖已經(jīng)被其他全局事務(wù)占有,則回滾 SELECT FOR UPDATE 語(yǔ)句的執(zhí)行,釋放本地鎖,并且重試 SELECT FOR UPDATE 語(yǔ)句。在這個(gè)過(guò)程中,查詢請(qǐng)求會(huì)被阻塞,直到拿到全局鎖(也就是要讀取的記錄被其他全局事務(wù)提交),讀到已被全局事務(wù)提交的數(shù)據(jù)才返回。這個(gè)過(guò)程如下圖所示:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理
1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

4. 結(jié)束語(yǔ)

XA 協(xié)議是 X/Open 提出的分布式事務(wù)處理標(biāo)準(zhǔn)。文中提到的 2PC、3PC、TCC、本地事務(wù)表、Seata in AT mode,無(wú)論哪一種,本質(zhì)都是事務(wù)協(xié)調(diào)者協(xié)調(diào)各個(gè)事務(wù)參與者的本地事務(wù)的進(jìn)度,使使所有本地事務(wù)共同提交或回滾,最終達(dá)成一種全局的 ACID 特性。在協(xié)調(diào)的過(guò)程中,協(xié)調(diào)者需要收集各個(gè)本地事務(wù)的當(dāng)前狀態(tài),并根據(jù)這些狀態(tài)發(fā)出下一階段的操作指令。這個(gè)思想就是 XA 協(xié)議的要義,我們可以說(shuō)這些事務(wù)模型遵守或大致遵守了 XA 協(xié)議。

基于消息中間件的最終一致性事務(wù)方案是互聯(lián)網(wǎng)公司在高并發(fā)場(chǎng)景中探索出的一種創(chuàng)新型應(yīng)用模式,利用 MQ 實(shí)現(xiàn)微服務(wù)之間的異步調(diào)用、解耦合和流量削峰,保證分布式數(shù)據(jù)記錄的最終一致性。它顯然不遵守 XA 協(xié)議。

對(duì)于某項(xiàng)技術(shù),可能存在業(yè)界標(biāo)準(zhǔn)或協(xié)議,但實(shí)踐者針對(duì)具體應(yīng)用場(chǎng)景的需求或者出于簡(jiǎn)便的考慮,給出與標(biāo)準(zhǔn)不完全相符的實(shí)現(xiàn),甚至完全不相符的實(shí)現(xiàn),這在工程領(lǐng)域是一種常見(jiàn)的現(xiàn)象。TCC 方案如此、基于消息中間件的最終一致性事務(wù)方案如此、Seata in AT mode 模式也如此。而新的標(biāo)準(zhǔn)往往就在這些創(chuàng)新中產(chǎn)生。

。

。

。

。

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

你難道真的沒(méi)有發(fā)現(xiàn) 2.6 節(jié)(基于消息中間件的最終一致性事務(wù)方案)給出的正確方案中存在的業(yè)務(wù)漏洞嗎?請(qǐng)各位重新看下這張圖,仔細(xì)品一品兩個(gè)微服務(wù)的調(diào)用方向,把你的想法留在評(píng)論區(qū)吧 :-)

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

長(zhǎng)按訂閱更多精彩▼

1.4 w字,25張圖讓你徹底掌握分布式事務(wù)原理

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉