1. 程式人生 > >玩轉KafkaIO與Flink微服務架構的分布式事務

玩轉KafkaIO與Flink微服務架構的分布式事務

http 就是 req 網上購物 恢復 其它 本質 強一致 上鎖

一、盡量在業務上和技術上避免分布式事務 顯而易見,微服務架構十分的流行,特別是對於電商領域來說。他的優點就不多說了,但是隨著集群機器的增加,集群的規模也越來越大,隨著集群搭載的服務規模也越來越大,導致事務的處理也就越來越復雜,有可能一個事務涉及到n多個服務,可想而知就算再優良的方案也很難處理這麽復雜的事務,與其硬著頭皮犧牲性能和可靠性,還不如改變業務,再結合技術對事務進行分割,將復雜的事務簡單化,將簡單的事務消化化。 二、兩段式提交(2PC),XA/JTA已經實現了 在分布式系統中,每個節點雖然可以知曉自己的操作是成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的組件來統一掌控所有節點(參與者)的操作結果並最終指示這些節點是否需要把操作結果進行真正的提交。算法步驟如下: 第一階段: 1、協調者會問所有的參與者,是否可以執行提交操作。 2、各個參與者開始事務執行的準備工作,如:為資源上鎖,預留資源。 3、參與者響應協調者,如果事務的準備工作成功,則回應“可以提交”,否則回應“拒絕提交”。 第二階段: 1、如果所有的參與者都回應“可以提交”。那麽協調者向所有的參與者發送“正式提交”的命令。參與者完成正式提交並釋放所有資源,然後回應“完成”,協調者收集各節點的“完成”回應後結束這個Global Transaction 2、如果有一個參與者回應“拒絕提交”,那麽協調者向所有的參與者發送“回滾操作”,並釋放所有資源,然後回應“回滾完成”,協調者收集各節點的“回滾”回應後,取消這個Global Transaction。

技術分享圖片

圖片描述(最多50字)

我們可以看到,2PC說白了就是第一階段做Vote,第二階段做決定的一個算法,也可以看到2PC這個事是強一致性的算法。2PC用的是比較多的,在一些系統設計中,會串聯一系列的調用,比如:A -> B -> C -> D,每一步都會分配一些資源或改寫一些數據。比如我們B2C網上購物的下單操作在後臺會有一系列的流程需要做。如果我們一步一步地做,就會出現這樣的問題,如果某一步做不下去了,那麽前面每一次所分配的資源需要做反向操作把他們都回收掉,所以,操作起來比較復雜。現在很多處理流程(Workflow)都會借鑒2PC這個算法,使用 try -> confirm的流程來確保整個流程的能夠成功完成。? ?另外,我們也可以看到其中的一些問題,

A)其中一個是同步阻塞操作,這個事情必然會非常大地影響性能。?

B)另一個主要的問題是在TimeOut上,比如,

1)如果第一階段中,參與者沒有收到詢問請求,或是參與者的回應沒有到達協調者。那麽,需要協調者做超時處理,一旦超時,可以當作失敗,也可以重試。

2)如果第二階段中,正式提交發出後,如果有的參與者沒有收到,或是參與者提交/回滾後的確認信息沒有返回,一旦參與者的回應超時,要麽重試,要麽把那個參與者標記為問題結點剔除整個集群,這樣可以保證服務結點都是數據一致性的。

3)糟糕的情況是,第二階段中,如果參與者收不到協調者的commit/fallback指令,參與者將處於“狀態未知”階段,參與者完全不知道要怎麽辦,比如:如果所有的參與者完成第一階段的回復後(可能全部yes,可能全部no,可能部分yes部分no),如果協調者在這個時候掛掉了。那麽所有的結點完全不知道怎麽辦(問別的參與者都不行)。為了一致性,要麽死等協調者,要麽重發第一階段的yes/no命令。

兩段提交最大的問題就是第3)項,如果第一階段完成後,參與者在第二階沒有收到決策,那麽數據結點會進入“不知所措”的狀態,這個狀態會block住整個事務。也就是說,協調者Coordinator對於事務的完成非常重要,Coordinator的可用性是個關鍵。 因些,我們有了三段提交。

三、三段式(3PC)提交(三段式提交實現起來非常的復雜,所以很少被使用)

三段提交的核心理念是:在詢問的時候並不鎖定資源,除非所有人都同意了,才開始鎖資源。他把二段提交的第一個段break成了兩段:詢問,然後再鎖資源。最後真正提交。

技術分享圖片

圖片描述(最多50字)

四、Paxos算法

Paxos 算法解決的問題是在一個可能發生上述異常的分布式系統中如何就某個值達成一致,保證不論發生以上任何異常, 都不會破壞決議的一致性。一個典型的場景是,在一個分布式數據庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麽他們最後能得到一個一致的狀態。為保證每個節點執行相同的命令序列,需要在每一條指令上執行一個「一致性算法」以保證每個節點看到的指令一致。一個通用的一致性算法可以應用在許多場景中,是分布式計算中的重要問題。從20世紀80年代起對於一致性算法的研究就沒有停止過。

簡單說來,Paxos的目的是讓整個集群的結點對某個值的變更達成一致。Paxos算法基本上來說是個民主選舉的算法——大多數的決定會成個整個集群的統一決定。任何一個點都可以提出要修改某個數據的提案,是否通過這個提案取決於這個集群中是否有超過半數的結點同意(所以Paxos算法需要集群中的結點是單數)

這個算法有兩個階段(假設這個有三個結點:A,B,C):

第一階段:Prepare階段

A把申請修改的請求Prepare Request發給所有的結點A,B,C。註意,Paxos算法會有一個Sequence Number(你可以認為是一個提案號,這個數不斷遞增,而且是唯一的,也就是說A和B不可能有相同的提案號),這個提案號會和修改請求一同發出,任何結點在“Prepare階段”時都會拒絕其值小於當前提案號的請求。所以,結點A在向所有結點申請修改請求的時候,需要帶一個提案號,越新的提案,這個提案號就越是 ? ? ? 最大的。如果接收結點收到的提案號n大於其它結點發過來的提案號,這個結點會回應Yes(本結點上最新的被批準提案號),並保證不接收其它<n的提案。這樣一來,結點上在Prepare階段裏總是會對最新的提案做承諾。

優化:在上述 prepare 過程中,如果任何一個結點發現存在一個更高編號的提案,則需要通知 提案人,提醒其中斷這次提案。

第二階段:Accept階段

如果提案者A收到了超過半數的結點返回的Yes,然後他就會向所有的結點發布Accept Request(同樣,需要帶上提 案號n),如果沒有超過半數的話,那就返回失敗。

當結點們收到了Accept Request後,如果對於接收的結點來說,n是最大的了,那麽,它就會修改這個值,如果發現自己有一個更大的提案號,那麽,結點就會拒絕修改。

我們可以看以,這似乎就是一個“兩段提交”的優化。其實,2PC/3PC都是分布式一致性算法的殘次版本,Google Chubby的作者Mike Burrows說過這個世界上只有一種一致性算法,那就是Paxos,其它的算法都是殘次品。

五、補償性的TCC類型

所謂的TCC編程模式,也是兩階段提交的一個變種。TCC提供了一個編程框架,將整個業務邏輯分為三塊:Try、Confirm和Cancel三個操作。以在線下單為例,Try階段會去扣庫存,Confirm階段則是去更新訂單狀態,如果更新訂單失敗,則進入Cancel階段,會去恢復庫存。總之,TCC就是通過代碼人為實現了兩階段提交,不同的業務場景所寫的代碼都不一樣,復雜度也不一樣,因此,這種模式並不能很好地被復用。

六、消息事務+最終一致性(異步確保型)

所謂的消息事務就是基於消息中間件的兩階段提交,本質上是對消息中間件的一種特殊利用,它是將本地事務和發消息放在了一個分布式事務裏,保證要麽本地操作成功成功並且對外發消息成功,要麽兩者都失敗,開源的RocketMQ就支持這一特性,具體原理如下:

技術分享圖片

圖片描述(最多50字)

1、A系統向消息中間件發送一條預備消息

2、消息中間件保存預備消息並返回成功

3、A執行本地事務

4、A發送提交消息給消息中間件

通過以上4步完成了一個消息事務。對於以上的4個步驟,每個步驟都可能產生錯誤,下面一一分析:

步驟一出錯,則整個事務失敗,不會執行A的本地操作

步驟二出錯,則整個事務失敗,不會執行A的本地操作

步驟三出錯,這時候需要回滾預備消息,怎麽回滾?答案是A系統實現一個消息中間件的回調接口,消息中間件會去不斷執行回調接口,檢查A事務執行是否執行成功,如果失敗則回滾預備消息

步驟四出錯,這時候A的本地事務是成功的,那麽消息中間件要回滾A嗎?答案是不需要,其實通過回調接口,消息中間件能夠檢查到A 執行成功了,這時候其實不需要A發提交消息了,消息中間件可以自己對消息進行提交,從而完成整個消息事務

基於消息中間件的兩階段提交往往用在高並發場景下,將一個分布式事務拆成一個消息事務(A系統的本地操作+發消息)+B系統的本地操作,其中B系統的操作由消息驅動,只要消息事務成功,那麽A操作一定成功,消息也一定發出來了,這時候B會收到消息去執行本地操作,如果本地操作失敗,消息會重投,直到B操作成功,這樣就變相地實現了A與B的分布式事務。原理如下:

技術分享圖片

圖片描述(最多50字)

雖然上面的方案能夠完成A和B的操作,但是A和B並不是嚴格一致的,而是最終一致的,我們在這裏犧牲了一致性,換來了性能的大幅度提升。當然,這種玩法也是有風險的,如果B一直執行不成功,那麽一致性會被破壞,具體要不要玩,還是得看業務能夠承擔多少風險。

技術分享圖片

圖片描述(最多50字)

七、最大努力通知型

按規律進行通知,不保證數據一定能通知成功,但會提供可查詢操作接口進行核對。這種方案主要用在與第三方系統通訊時,比如:調用微信或支付寶支付後的支付結果通知。這種方案也是結合MQ進行實現,例如:通過MQ發送http請求,設置最大通知次數。達到通知次數後即不再通知。

技術分享圖片

圖片描述(最多50字)

玩轉KafkaIO與Flink微服務架構的分布式事務