TCC
關于TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年發表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出。
TCC事務機制相比于上面介紹的XA,解決了其幾個缺點:
1.解決了協調者單點,由主業務方發起并完成這個業務活動。業務活動管理器也變成多點,引入叢集。
2.同步阻塞:引入逾時,逾時後進行補償,并且不會鎖定整個資源,将資源轉換為業務邏輯形式,粒度變小。
3.資料一緻性,有了補償機制之後,由業務活動管理器控制一緻性

對于TCC的解釋:
Try階段:嘗試執行,完成所有業務檢查(一緻性),預留必須業務資源(準隔離性)
Confirm階段:确認執行真正執行業務,不作任何業務檢查,隻使用Try階段預留的業務資源,Confirm操作滿足幂等性。要求具備幂等設計,Confirm失敗後需要進行重試。
Cancel階段:取消執行,釋放Try階段預留的業務資源
Cancel操作滿足幂等性Cancel階段的異常和Confirm階段異常處理方案基本上一緻。
舉個簡單的例子如果你用100元買了一瓶水,
Try階段:你需要向你的錢包檢查是否夠100元并鎖住這100元,水也是一樣的。
如果有一個失敗,則進行cancel(釋放這100元和這一瓶水),如果cancel失敗不論什麼失敗都進行重試cancel,是以需要保持幂等。
如果都成功,則進行confirm,确認這100元扣,和這一瓶水被賣,如果confirm失敗無論什麼失敗則重試(會依靠活動日志進行重試)
對于TCC來說适合一些:
強隔離性,嚴格一緻性要求的活動業務。
執行時間較短的業務
本地消息表
本地消息表這個方案最初是ebay提出的 ebay的完整方案https://queue.acm.org/detail.cfm?id=1394128。
此方案的核心是将需要分布式處理的任務通過消息日志的方式來異步執行。消息日志可以存儲到本地文本、資料庫或消息隊列,再通過業務規則自動或人工發起重試。人工重試更多的是應用于支付場景,通過對賬系統對事後問題的處理。
對于本地消息隊列來說核心是把大事務轉變為小事務。還是舉上面用100元去買一瓶水的例子。
1.當你扣錢的時候,你需要在你扣錢的伺服器上新增加一個本地消息表,你需要把你扣錢和寫入減去水的庫存到本地消息表放入同一個事務(依靠資料庫本地事務保證一緻性。
2.這個時候有個定時任務去輪詢這個本地事務表,把沒有發送的消息,扔給商品庫存伺服器,叫他減去水的庫存,到達商品伺服器之後這個時候得先寫入這個伺服器的事務表,然後進行扣減,扣減成功後,更新事務表中的狀态。
3.商品伺服器通過定時任務掃描消息表或者直接通知扣錢伺服器,扣錢伺服器本地消息表進行狀态更新。
4.針對一些異常情況,定時掃描未成功處理的消息,進行重新發送,在商品伺服器接到消息之後,首先判斷是否是重複的,如果已經接收,在判斷是否執行,如果執行在馬上又進行通知事務,如果未執行,需要重新執行需要由業務保證幂等,也就是不會多扣一瓶水。
本地消息隊列是BASE理論,是最終一緻模型,适用于對一緻性要求不高的。實作這個模型時需要注意重試的幂等。
MQ事務
在RocketMQ中實作了分布式事務,實際上其實是對本地消息表的一個封裝,将本地消息表移動到了MQ内部,下面簡單介紹一下MQ事務,
基本流程如下:
第一階段Prepared消息,會拿到消息的位址。
第二階段執行本地事務。
第三階段通過第一階段拿到的位址去通路消息,并修改狀态。消息接受者就能使用這個消息。
如果确認消息失敗,在RocketMq Broker中提供了定時掃描沒有更新狀态的消息,如果有消息沒有得到确認,會向消息發送者發送消息,來判斷是否送出,在rocketmq中是以listener的形式給發送者,用來處理。
如果消費逾時,則需要一直重試,消息接收端需要保證幂等。如果消息消費失敗,這個就需要人工進行處理,因為這個機率較低,如果為了這種小機率時間而設計這個複雜的流程反而得不償失
轉自:https://juejin.im/post/5b729aeef265da281244d9a5