Categories
程式開發

兩天,我把分佈式事務搞完了


每個時代,都不會虧待會學習的人。

大家好,我是yes。

今天我想和大家一起盤一盤分佈式事務,會介紹常見的分佈式事務實現方案和其優缺點以及適用的場景,並會帶出它們的一些變體實現。

還會捎帶一下分佈式數據庫對2PC 的改進模型,看看分佈式數據庫是如何做的。

然後再分析一波分佈式事務框架Seata 的具體實現,看看分佈式事務究竟是如何落地的,畢竟協議要落地才是有用的。

兩天,我把分佈式事務搞完了 1

首先我們來提一下事務和分佈式事務是什麼。

事務

事務的ACID 想必大家都熟知,這其實是嚴格意義上的定義,指的是事務的實現必須具備原子性、一致性、隔離性和持久性。

不過嚴格意義上的事務很難達到,像我們熟知的數據庫就有各種隔離級別,隔離級別越高性能越低,所以往往我們都會從中找到屬於自己的平衡,不會遵循嚴格意義上的事務。

並且在我們平日的談論中,所謂的事務往往簡單的指代一系列的操作全部執行成功,或者全部失敗,不會出現一些成功一些失敗的情形。

清晰了平日我們對事務的定義之後,再來看看什麼是分佈式事務。

分佈式事務

由於互聯網的快速發展,以往的單體架構頂不住這麼多的需求,這麼複雜的業務,這麼大的流量。

單體架構的優勢在於前期快速搭建、快速上線,並且方法和模塊之間都是內部調用,沒有網絡的開銷更加的高效。

從某方面來說部署也方便,畢竟就一個包,扔上去。

不過隨著企業的發展,業務的複雜度越來越高,內部耦合極其嚴重,導致牽一發而動全身,開發不易,測試不易。

並且無法根據熱點服務進行動態的伸縮,比如商品服務訪問量特別大,如果是單體架構的話我們只能把整個應用複制多份集群部署,浪費資源。

因此拆分勢在必行,微服務架構就這麼來了。

兩天,我把分佈式事務搞完了 2

拆分之後服務之間的邊界就清晰了,每個服務都能獨立地運行,獨立地部署,所以能以服務級別彈性伸縮了。

服務之間的本地調用變成了遠程調用,鏈路更長了,一次調用的耗時更長了,但是總體的吞吐量更大了。

不過拆分之後還會引入其他復雜度,比如服務鏈路的監控、整體的監控、容錯措施、彈性伸縮等等運維監控的問題,還有像分佈式事務、分佈式鎖跟業務息息相關的問題等。

往往解決了一個痛點又會引入別的痛點,所以架構的演進都是權衡的結果,就看你們的系統更能忍受哪種痛點了。

而今天我們談及的就是分佈式事務這個痛點。

分佈式事務是由多個本地事務組成的,分佈式事務跨越了多設備,之間又經歷的複雜的網絡,可想而知想要實現嚴格的事務道路阻且長。

單機版事務都不會嚴格遵守事務的嚴格實現,更別說分佈式事務了,所以在現實情況下我​​們只能實現殘缺版的事務。

在明確了事務和分佈式事務之後,我們就先來看看常見的分佈式事務方案:2PC、3PC、TCC、本地消息、事務消息。

2個

2PC,Two-phase commit protocol,即兩階段提交協議。

它引入了一個事務協調者角色,來管理各個參與者(就是各數據庫資源)。

整體分為兩個階段,分別是準備階段和提交/回滾階段。

我們先來看看第一個階段,即準備階段。

兩天,我把分佈式事務搞完了 3

由事務協調者給每個參與者發送準備命令,每個參與者收到命令之後會執行相關事務操作,你可以認為除了事務的提交啥都做了。

然後每個參與者會返迴響應告知協調者自己是否準備成功。

協調者收到每個參與者的響應之後就進入第二階段,根據收集的響應,如果有一個參與者響應準備失敗那麼就向所有參與者發送回滾命令,反之發送提交命令。

兩天,我把分佈式事務搞完了 4

這個協議其實很符合正常的思維,就像我們大學上課點名的時候,其實老師就是協調者的角色,我們都是參與者。

老師一個一個的點名,我們一個一個的喊到,最後老師收到所有同學的到之後就開始了今天的講課。

而和點名有所不同的是,老師發現某幾個學生不在還是能繼續上課,而我們的事務可不允許這樣。

事務協調者在第一階段未收到個別參與者的響應,則等待一定時間就會認為事務失敗,會發送回滾命令,所以在2PC 中事務協調者有超時機制。

我們再來分析一下2PC 的優缺點。

2PC 的優點是能利用數據庫自身的功能進行本地事務的提交和回滾,也就是說提交和回滾實際操作不需要我們實現,不侵入業務邏輯由數據庫完成,在之後講解TCC 之後相信大家對這點會有所體會。

2PC 主要有三大缺點:同步阻塞、單點故障和數據不一致問題。

兩天,我把分佈式事務搞完了 5

同步阻塞

可以看到在第一階段執行了準備命令後,我們每個本地資源都處於鎖定狀態,因為除了事務的提交之外啥都做了。

所以這時候如果本地的其他請求要訪問同一個資源,比如要修改商品表id 等於100 的那條數據,那麼此時是被阻塞住的,必須等待前面事務的完結,收到提交/回滾命令執行完釋放資源後,這個請求才能得以繼續。

所以假設這個分佈式事務涉及到很多參與者,然後有些參與者處理又特別複雜,特別慢,那麼那些處理快的節點也得等著,所以說效率有點低。

單點故障

可以看到這個單點就是協調者,如果協調者掛了整個事務就執行不下去了。

如果協調者在發送準備命令前掛了還行,畢竟每個資源都還未執行命令,那麼資源是沒被鎖定的。

可怕的是在發送完準備命令之後掛了,這時候每個本地資源都執行完處於鎖定狀態了,都杵著了,這就很僵硬了,如果是某個熱點資源都阻塞了,這估計就要GG了。

兩天,我把分佈式事務搞完了 6

數據不一致問題

因為協調者和參與者之間的交流是經過網絡的,而網絡有時候就會抽風的或者發生局部網絡異常。

那麼就有可能導致某些參與者無法收到協調者的請求,而某些收到了。 比如是提交請求,然後那些收到命令的參與者就提交事務了,此時就產生了數據不一致的問題。

小結一下2PC

至此我們來先小結一些2PC ,它是一個同步阻塞的強一致性兩階段提交協議,分別是準備階段和提交/回滾階段。

2PC 的優勢在於對業務沒有侵入,可以利用數據庫自身機制來進行事務的提交和回滾。

它的缺點:是一個同步阻塞協議,會導致高延遲和性能的下降,並且存在協調者單點故障問題,極端情況下會有數據不一致的問題。

當然這只是協議,具體的落地還是可以變通了,比如協調者單點問題,我就搞個主從來實現協調者,對吧。

分佈式數據庫的2PC 改進模型

可能有些人對分佈式數據庫不熟悉,沒有關係,我們主要學的是思想,看看人家的思路。

我簡單的講下Percolator 模型,它是基於分佈式存儲系統BigTable 建立的模型,BigTable 是啥也不清楚的同學沒有關係影響不大。

還是拿轉賬的例子來說,我現在有200 塊錢,你現在有100 塊錢,為了突出重點我也不按正常的結構來畫這個表。

兩天,我把分佈式事務搞完了 7

然後我要轉100 塊給你。

兩天,我把分佈式事務搞完了 8

此時事務管理器發起了準備請求,然後我賬上的錢就少了,你賬上的錢就多了,而且事務管理器還記錄下這次操作的日誌。

此時的數據還是私有版本,別的事務是讀不到的,簡單的理解Lock 上有值就還是私有的。

可以看到我的記錄Lock 標記的是PK,你的記錄標記的是指向我的記錄指針,這個PK 是隨機選擇的。

然後事務管理器會向被選擇作為PK 的那條記錄發起提交指令。

兩天,我把分佈式事務搞完了 9

此時就會把我的記錄的鎖給抹去了,這等於我的記錄不再是私有版本了,別的事務就都能訪問了。

那你的記錄上還有鎖啊? 不用更新嗎?

嘿嘿不需要及時更新,因為訪問你的這條記錄的時候會去根據指針找我的那個記錄,發現記錄已經提交了所以你的記錄就可以被訪問了。

有人說這效率不就差了,每次都要去找一次,別急。

後台會有個線程來掃描,然後更新把鎖記錄給去了。

這不就穩了嘛。

相比於2PC 的改進

首先Percolator 在提交階段不需要和所有的參與者交互,主需要和一個參與者打交道,所以這個提交是原子的! 解決了數據不一致問題。

然後事務管理器會記錄操作日誌,這樣當事務管理器掛了之後選舉的新事務管理器就可以通過日誌來得知當前的情況從而繼續工作,解決了單點故障問題。

並且Percolator 還會有後台線程,會掃描事務狀況,在事務管理器宕機之後會回滾各個參與者上的事務。

可以看到相對於2PC 還是做了很多改進的,也是巧妙的。

其實分佈式數據庫還有別的事務模型,不過我也不太熟悉,就不多嗶嗶了,有興趣的同學可以自行了解。

還是挺能拓寬思想的。

XA 規範

讓我們再回來2PC,既然說到2PC 了那麼也簡單的提一下XA 規範,XA 規範是基於兩階段提交的,它實現了兩階段提交協議。

在說XA 規範之前又得先提一下DTP 模型,即Distributed Transaction Processing,這模型規範了分佈式事務的模型設計。

而XA 規範又約束了DTP 模型中的事務管理器(TM) 和資源管理器(RM)之間的交互,簡單的說就是你們兩之間要按照一定的格式規範來交流!

我們先來看下XA 約束下的DTP 模型。

兩天,我把分佈式事務搞完了 10

AP 應用程序,就是我們的應用,事務的發起者。 RM 資源管理器,簡單的認為就是數據庫,具備事務提交和回滾能力,對應我們上面的2PC 就是參與者。 TM 事務管理器,就是協調者了,和每個RM 通信。

簡單的說就是AP 通過TM 來定義事務操作,TM 和RM 之間會通過XA 規范進行通信,執行兩階段提交,而AP 的資源是從RM 拿的。

從模型上看有三個角色,而實際實現可以由一個角色實現兩個功能,比如AP 來實現TM 的功能,TM 沒必要抽出來單獨部署。

MySQL XA

知曉了DTP 之後,我們就來看看XA 在MySQL 中是如何操作的,不過只有InnoDB 支持。

簡單的說就是要先定義一個全局唯一的XID,然後告知每個事務分支要進行的操作。

可以看到圖中執行了兩個操作,分別是改名字和插入日誌,等於先註冊下要做的事情,通過XA START XID 和XA END XID 來包裹要執行的SQL。

兩天,我把分佈式事務搞完了 11

然後需要發送準備命令,來執行第一階段,也就是除了事務的提交啥都乾了的階段。

兩天,我把分佈式事務搞完了 12

然後根據準備的情況來選擇執行提交事務命令還是回滾事務命令。

兩天,我把分佈式事務搞完了 13

基本上就是這麼個流程,不過MySQL XA 的性能不高這點是需要注意的。

可以看到雖說2PC 有缺點,但是還是有基於2PC 的落地實現的,而3PC 的引出是為了解決2PC 的一些缺點,但是它整體下來開銷更大,也解決不了網絡分區的問題,我也沒有找到3PC 的落地實現。

不過我還是稍微提一下,知曉一下就行,純理論。

3台

3PC 的引入是為了解決2PC 同步阻塞和減少數據不一致的情況。

3PC 也就是多了一個階段,一個詢問的階段,分別是準備、預提交和提交這三個階段。

準備階段單純就是協調者去訪問參與者,類似於你還好嗎? 能接請求不。

預提交其實就是2PC 的準備階段,除了事務的提交啥都乾了。

提交階段和2PC 的提交一致。

兩天,我把分佈式事務搞完了 14

3PC 多了一個階段其實就是在執行事務之前來確認參與者是否正常,防止個別參與者不正常的情況下,其他參與者都執行了事務,鎖定資源。

出發點是好的,但是絕大部分情況下肯定是正常的,所以每次都多了一個交互階段就很不划算。

然後3PC 在參與者處也引入了超時機制,這樣在協調者掛了的情況下,如果已經到了提交階段了,參與者等半天沒收到協調者的情況的話就會自動提交事務。

不過萬一協調者發的是回滾命令呢? 你看這就出錯了,數據不一致了。

還有維基百科上說2PC 參與者準備階段之後,如果協調者掛了,參與者是無法得知整體的情況的,因為大局是協調者掌控的,所以參與者相互之間的狀況它們不清楚。

而3PC 經過了第一階段的確認,即使協調者掛了參與者也知道自己所處預提交階段是因為已經得到準備階段所有參與者的認可了。

簡單的說就像加了個圍欄,使得各參與者的狀態得以統一。

小結2PC 和3PC

從上面已經知曉了2PC 是一個強一致性的同步阻塞協議,性能已經是比較差的了。

而3PC 的出發點是為了解決2PC 的缺點,但是多了一個階段就多了一次通訊的開銷,而且是絕大部分情況下無用的通訊。

雖說引入參與者超時來解決協調者掛了的阻塞問題,但是數據還是會不一致。

可以看到3PC 的引入並沒什麼實際突破,而且性能更差了,所以實際只有2PC 的落地實現。

再提一下,2PC 還是3PC 都是協議,可以認為是一種指導思想,和真正的落地還是有差別的。

兩天,我把分佈式事務搞完了 15

TCC

不知道大家注意到沒,不管是2PC 還是3PC 都是依賴於數據庫的事務提交和回滾。

而有時候一些業務它不僅僅涉及到數據庫,可能是發送一條短信,也可能是上傳一張圖片。

所以說事務的提交和回滾就得提升到業務層面而不是數據庫層面了,而TCC 就是一種業務層面或者是應用層的兩階段提交。

TCC 分為指代Try、Confirm、Cancel ,也就是業務層面需要寫對應的三個方法,主要用於跨數據庫、跨服務的業務操作的數據一致性問題。

TCC 分為兩個階段,第一階段是資源檢查預留階段即Try,第二階段是提交或回滾,如果是提交的話就是執行真正的業務操作,如果是回滾則是執行預留資源的取消,恢復初始狀態。

比如有一個扣款服務,我需要寫Try 方法,用來凍結扣款資金,還需要一個Confirm 方法來執行真正的扣款,最後還需要提供Cancel 來進行凍結操作的回滾,對應的一個事務的所有服務都需要提供這三個方法。

可以看到本來就一個方法,現在需要膨脹成三個方法,所以說TCC 對業務有很大的侵入,像如果沒有凍結的那個字段,還需要改表結構。

我們來看下流程。

兩天,我把分佈式事務搞完了 16

雖說對業務有侵入,但是TCC 沒有資源的阻塞,每一個方法都是直接提交事務的,如果出錯是通過業務層面的Cancel 來進行補償,所以也稱補償性事務方法。

這裡有人說那要是所有人Try 都成功了,都執行Comfirm 了,但是個別Confirm 失敗了怎麼辦?

這時候只能是不停地重試調失敗了的Confirm 直到成功為止,如果真的不行只能記錄下來,到時候人工介入了。

TCC 的注意點

這幾個點很關鍵,在實現的時候一定得注意了。

兩天,我把分佈式事務搞完了 17

冪等問題,因為網絡調用無法保證請求一定能到達,所以都會有重調機制,因此對於Try、Confirm、Cancel 三個方法都需要冪等實現,避免重複執行產生錯誤。

空回滾問題,指的是Try 方法由於網絡問題沒收到超時了,此時事務管理器就會發出Cancel 命令,那麼需要支持Cancel 在未執行Try 的情況下能正常的Cancel。

懸掛問題,這個問題也是指Try 方法由於網絡阻塞超時觸發了事務管理器發出了Cancel 命令,但是執行了Cancel 命令之後Try 請求到了,你說氣不氣。

這都Cancel 了你來個Try,對於事務管理器來說這時候事務已經是結束了的,這凍結操作就被“懸掛”了,所以空回滾之後還得記錄一下,防止Try 的再調用。

TCC 變體

上面我們說的是通用型的TCC,它需要改造以前的實現,但是有一種情況是無法改造的,就是你調用的是別的公司的接口。

沒有Try 的TCC

比如坐飛機需要換乘,換乘的又是不同的航空公司,比如從A 飛到B,再從B 飛到C,只有A – B 和B – C 都買到票了才有意義。

這時候的選擇就沒得Try 了,直接調用航空公司的買票操作,當兩個航空公司都買成功了那就直接成功了,如果某個公司買失敗了,那就需要調用取消訂票接口。

也就是在第一階段直接就執行完整個業務操作了,所以要重點關注回滾操作,如果回滾失敗得有提醒,要人工介入等。

這其實就是TCC 的思想。

兩天,我把分佈式事務搞完了 18

異步TCC

這TCC 還能異步? 其實也是一種折中,比如某些服務很難改造,並且它又不會影響主業務決策,也就是它不那麼重要,不需要及時的執行。

這時候可以引入可靠消息服務,通過消息服務來替代個別服務來進行Try、Confirm、Cancel 。

Try 的時候只是寫入消息,消息還不能被消費,Confirm 就是真正發消息的操作,Cancel 就是取消消息的發送。

這可靠消息服務其實就類似於等下要提到的事務消息,這個方案等於糅合了事務消息和TCC。

TCC 小結

可以看到TCC 是通過業務代碼來實現事務的提交和回滾,對業務的侵入較大,它是業務層面的兩階段提交,。

它的性能比2PC 要高,因為不會有資源的阻塞,並且適用範圍也大於2PC,在實現上要注意上面提到的幾個注意點。

它是業界比較常用的分佈式事務實現方式,而且從變體也可以得知,還是得看業務變通的,不是說你要用TCC 一定就得死板的讓所有的服務都改造成那三個方法。

本地消息表

本地消息就是利用了本地事務,會在數據庫中存放一直本地事務消息表,在進行本地事務操作中加入了本地消息的插入,即將業務的執行和將消息放入消息表中的操作放在同一個事務中提交

這樣本地事務執行成功的話,消息肯定也插入成功,然後再調用其他服務,如果調用成功就修改這條本地消息的狀態。

如果失敗也不要緊,會有一個後台線程掃描,發現這些狀態的消息,會一直調用相應的服務,一般會設置重試的次數,如果一直不行則特殊記錄,待人工介入處理。

可以看到還是很簡單的,也是一種最大努力通知思想。

兩天,我把分佈式事務搞完了 19

事務消息

這個其實我寫過一篇文章,專門講事務消息,從源碼層面剖析了RocketMQ 、Kafka 的事務消息實現,以及兩者之間的區別。

在這裡我不再詳細闡述,因為之前的文章寫的很詳細了,大概四五千字吧。 我就附上鍊接了:事務消息

Seata 的實現

首先什麼是Seata ,摘抄官網的一段話。

Seata 是一款開源的分佈式事務解決方案,致力於提供高性能和簡單易用的分佈式事務服務。 Seata 將為用戶提供了AT、TCC、SAGA 和XA 事務模式,為用戶打造一站式的分佈式解決方案。

可以看到提供了很多模式,我們先來看看AT 模式。

AT模式

AT 模式就是兩階段提交,前面我們提到了兩階段提交有同步阻塞的問題,效率太低了,那Seata 是怎麼解決的呢?

AT 的一階段直接就把事務提交了,直接釋放了本地鎖,這麼草率直接提交的嘛? 當然不是,這里和本地消息表有點類似,就是利用本地事務,執行真正的事務操作中還會插入回滾日誌,然後在一個事務中提交。

這回滾日誌怎麼來的?

通過框架代理JDBC 的一些類,在執行SQL 的時候解析SQL 得到執行前的數據鏡像,然後執行SQL ,再得到執行後的數據鏡像,然後把這些數據組裝成回滾日誌。

再伴隨的這個本地事務的提交把回滾日誌也插入到數據庫的UNDOLOG 表中(所以數據庫需要有一張UNDOLOG 表)。

這波操作下來在一階段就可以沒有後顧之憂的提交事務了。

然後一階段如果成功,那麼二階段可以異步的刪除那些回滾日誌,如果一階段失敗那麼可以通過回滾日誌來反向補償恢復。

這時候有細心的同學想到了,萬一中間有人改了這條數據怎麼辦? 你這鏡像就不對了啊?

所以說還有個全局鎖的概念,在事務提交前需要拿到全局鎖(可以理解為對這條數據的鎖),然後才能順利提交本地事務。

如果一直拿不到那就需要回滾本地事務了。

官網的示例很好,我就不自己編了,以下部分內容摘抄自Seata 官網的示例:

此時有兩個事務,分別是tx1、和tx2,分別對a 表的m 字段進行更新操作,m 的初始值1000。

tx1 先開始,開啟本地事務,拿到本地鎖,更新操作m = 1000 – 100 = 900。 本地事務提交前,先拿到該記錄的全局鎖,本地提交釋放本地鎖。

tx2 後開始,開啟本地事務,拿到本地鎖,更新操作m = 900 – 100 = 800。 本地事務提交前,嘗試拿該記錄的全局鎖,tx1 全局提交前,該記錄的全局鎖被tx1 持有,tx2 需要重試等待全局鎖。

兩天,我把分佈式事務搞完了 20

可以看到tx2 的修改被阻塞了,之後重試拿到全局鎖之後就能提交然後釋放本地鎖。

如果tx1 的二階段全局回滾,則tx1 需要重新獲取該數據的本地鎖,進行反向補償的更新操作,實現分支的回滾。

此時,如果tx2 仍在等待該數據的全局鎖,同時持有本地鎖,則tx1 的分支回滾會失敗。 分支的回滾會一直重試,直到tx2 的全局鎖等鎖超時,放棄全局鎖並回滾本地事務釋放本地鎖,tx1 的分支回滾最終成功。

因為整個過程全局鎖在tx1 結束前一直是被tx1 持有的,所以不會發生臟寫的問題。

兩天,我把分佈式事務搞完了 21

然後AT 模式默認全局是讀未提交的隔離級別,如果應用在特定場景下,必需要求全局的讀已提交,可以通過SELECT FOR UPDATE 語句的代理。

當然前提是你本地事務隔離級別是讀已提交及以上。

AT 模式小結

可以看到通過代理來無侵入的得到數據的前後鏡像,組裝成回滾日誌伴隨本地事務一起提交,解決了兩階段的同步阻塞問題。

並且利用全局鎖來實現寫隔離。

為了總體性能的考慮,默認是讀未提交隔離級別,只代理了SELECT FOR UPDATE 來進行讀已提交的隔離。

這其實就是兩階段提交的變體實現。

TCC 模式

沒什麼花頭,就是咱們上面分析的需要搞三個方法, 然後把自定義的分支事務納入到全局事務的管理中

我貼一張官網的圖應該挺清晰了。

兩天,我把分佈式事務搞完了 22

Saga 模式

這個Saga 是Seata 提供的長事務解決方案,適用於業務流程多且長的情況下,這種情況如果要實現一般的TCC 啥的可能得嵌套多個事務了。

並且有些系統無法提供TCC 這三種接口,比如老項目或者別人公司的,所以就搞了個Saga 模式,這個Saga 是在1987 年Hector & Kenneth 發表的論⽂中提出的。

那Saga 如何做呢? 來看下這個圖。

兩天,我把分佈式事務搞完了 23

假設有N 個操作,直接從T1 開始就是直接執行提交事務,然後再執行T2,可以看到就是無鎖的直接提交,到T3 發現執行失敗了,然後就進入Compenstaing 階段,開始一個一個倒回補償了。

思想就是一開始蒙著頭乾,別慫,出了問題咱們再一個一個改回去唄。

可以看到這種情況是不保證事務的隔離性的,並且Saga 也有TCC 的一樣的注意點,需要空補償,防懸掛和冪等。

而且極端情況下會因為數據被改變了導致無法回滾的情況。 比如第一步給我打了2 萬塊錢,我給取出來花了,這時候你回滾,我賬上餘額已經0 了,你說怎麼辦嘛? 難道給我還搞負的不成?

這種情況只能在業務流程上入手,我寫代碼其實一直是這樣寫的,就拿買皮膚的場景來說,我都是先扣錢再給皮膚。

假設先給皮膚扣錢失敗了不就白給了嘛? 這錢你來補啊? 你覺得用戶會來反饋說皮膚給了錢沒扣嘛?

可能有小機靈鬼說我到時候把皮膚給改回去,嘿嘿這種事情確實發生過,嘖嘖,被罵的真慘。

所以正確的流程應該是先扣錢再給皮膚,錢到自己袋裡先,皮膚沒給成功用戶自然而然會找過來,這時候再給他唄,雖說可能你寫出了個BUG ,但是還好不是個白給的BUG。

所以說這點在編碼的時候還是得注意下的。

兩天,我把分佈式事務搞完了 24

最後

可以看到分佈式事務還是會有各種問題,一般分佈式事務的實現還是只能達到最終一致性。

極端情況下還是得人工介入,所以做好日誌記錄很關鍵。

還有編碼的業務流程,要往利於公司的方向寫,就例如先拿到用戶的錢,再給用戶東西這個方向,切記。

在上分佈式事務之前想想,有沒有必要,能不能改造一下避免分佈式事務?

再極端一點,你的業務有沒有必要上事務?

最後個人能力有限,如有紕漏請趕緊聯繫鞭撻我,如果覺得文章不錯還望點個在看支持一下喲。

巨人的肩膀

分佈式協議與算法實戰,韓健

分佈式數據庫30講,王磊

西塔

兩天,我把分佈式事務搞完了 25

我是yes,從一點點到億點點,我們下篇見。