億級流量架構之分佈式事務解決方案對比

上一篇文章( 億級流量架構之分佈式事務思路及方法)中梳理事務到分佈式事務的演變過程, 以及分佈式事務的處理思路,這篇文章主要從應用的角度對比目前較爲流行的一些分佈式事務方案,以及一些商業應用。html

想讓數據具備高可用性,就得寫多份數據,寫多份數據就會有數據一致性問題,數據已執行問題又會引起性能問題,因此如何權衡,是一件仁者見仁、智者見者的問題,目前的數據一致性,即分佈式事務,大概有以下幾種解決方案:git

  1. Master-Slave 方案。
  2. Master-Master 方案。
  3. 兩階段和三階段提交方案。
  4. Paxos 方案。

第3點在上篇文章中已經講過, 一、2這兒會簡單梳理,重點是第四個方案, 目前不少公司的事務處理方式,例如阿里巴巴的TCC(Try–Confirm–Cancel),亞馬遜的PRC(Plan–Reserve–Confirm)都是兩階段提交的變種, 凡是經過業務補償,或者是在業務層面上作的分佈式事務,基本都是兩階段提交的玩法,可是這否是應用層事務處理方式,而在數據層解決事務問題,Paxos是不二之選。github

Master-Slave 方案

這個也叫主從模式,Slave通常是Master的備份。在這樣的系統中,通常是以下設計的:redis

1)讀寫請求都由Master負責。算法

2)寫請求寫到Master上後,由Master同步到Slave上。數據庫

從Master同步到Slave上,你可使用異步,也可使用同步,可使用Master來push,也可使用Slave來pull。 一般來講是Slave來週期性的pull,因此,是最終一致性。編程

這個設計的問題是,若是Master在pull週期內垮掉了,那麼會致使這個時間片內的數據丟失。若是你不想讓數據丟掉,Slave只能成爲Read-Only的方式等Master恢復。api

若是能夠容忍數據丟掉的話,你能夠立刻讓Slave代替Master工做(對於只負責計算的結點來講,沒有數據一致性和數據丟失的問題,Master-Slave的方式就能夠解決單點問題了) ,Master Slave也能夠是強一致性的, 好比:當咱們寫Master的時候,Master負責先寫本身,等成功後,再寫Slave,二者都成功後返回成功,整個過程是同步的,若是寫Slave失敗了,那麼兩種方法,一種是標記Slave不可用報錯並繼續服務(等Slave恢復後同步Master的數據,能夠有多個Slave,這樣少一個,還有備份,也就是多個Slave),另外一種是回滾本身並返回寫失敗。架構

注:通常不先寫Slave,由於若是寫Master本身失敗後,還要回滾Slave,此時若是回滾Slave失敗,就得手工訂正數據框架

Master-Master 方案

Master-Master,主主模式,又叫Multi-master,是指一個系統存在兩個或多個Master,每一個Master都提供read-write服務。這個模型是Master-Slave的增強版,數據間同步通常是經過Master間的異步完成,因此是最終一致性。 Master-Master的好處是,一臺Master掛了,別的Master能夠正常作讀寫服務,他和Master-Slave同樣,當數據沒有被複制到別的Master上時,數據會丟失。不少數據庫都支持Master-Master的Replication的機制。

這種模式的問題在於: 若是多個Master對同一個數據進行修改的時候,這個模型的惡夢就出現了——對數據間的衝突合併,這並非一件容易的事情。爲了解決這問題, Dynamo提出了一種解決辦法, 記錄數據的版本號和修改者, 這也就意味着數據衝突這個事是交給用戶本身搞的。

兩階段和三階段提交方案

這個是業務層分佈式事務處理的核心, ,在上篇文章( 億級流量架構之分佈式事務思路及方法)中"二三階段提交協議"介紹得比較詳細了,這兒很少說。須要注意是這是重點,不太瞭解的朋友,爲了更好的理解後面的方案, 建議看看相關部分。

Paxos 方案

理解Paxos算法以前,先講一個情景——兩將軍問題,來理解這個算法是解決了什麼問題。

兩將軍問題

有兩支軍隊,它們分別有一位將軍領導,如今準備攻擊一座修築了防護工事的城市。這兩支軍隊都駐紮在那座城市的附近,分佔一座山頭。一道山谷把兩座山分隔開來,而且兩位將軍惟一的通訊方式就是派各自的信使來往于山谷兩邊。不幸的是,這個山谷已經被那座城市的保衛者佔領,而且存在一種可能,那就是任何被派出的信使經過山谷是會被捕。 請注意,雖然兩位將軍已經就攻擊那座城市達成共識,但在他們各自佔領山頭陣地以前,並無就進攻時間達成共識。兩位將軍必須讓本身的軍隊同時進攻城市才能取得成功。所以,他們必須互相溝通,以肯定一個時間來攻擊,並贊成就在那時攻擊。若是隻有一個將軍進行攻擊,那麼這將是一個災難性的失敗。 這個思惟實驗就包括考慮他們如何去作這件事情。下面是咱們的思考:

1)第一位將軍先發送一段消息「讓咱們在上午9點開始進攻」。然而,一旦信使被派遣,他是否經過了山谷,第一位將軍就不得而知了。任何一點的不肯定性都會使得第一位將軍攻擊猶豫,由於若是第二位將軍不能在同一時刻發動攻擊,那座城市的駐軍就會擊退他的軍隊的進攻,致使他的軍對被摧毀。

2)知道了這一點,第二位將軍就須要發送一個確認回條:「我收到您的郵件,並會在9點的攻擊。」可是,若是帶着確認消息的信使被抓怎麼辦?因此第二位將軍會猶豫本身的確認消息是否能到達。

3)因而,彷佛咱們還要讓第一位將軍再發送一條確認消息——「我收到了你的確認」。然而,若是這位信使被抓怎麼辦呢?

4)這樣一來,是否是咱們還要第二位將軍發送一個「確認收到你的確認」的信息。

靠,因而你會發現,這事情很快就發展成爲無論發送多少個確認消息,都沒有辦法來保證兩位將軍有足夠的自信本身的信使沒有被敵軍捕獲。

Paxos 算法

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

這個算法詳細解釋能夠參考維基百科以及raft算法(Paxos改進)做者的視頻(B站,YouTube),這兒我用本身的話敘述:

這個算法將節點分了不少類,官方定義爲:Client、Propose、 Acceptor、 Learner,含義不重要,先來理解他們的做用, 看個人文字就好了。

在咱們讀書的時候,班級裏有組長,有班委成員,有班務記錄員,下面一一對應起來:

加入咱們班決定這周沒去遊玩,如今班會討論去玩什麼項目:

Client : 表明普通同窗,能夠提出方案,須要將方案交給組長(Propose)

Propose : 組長,一個班確定有不少組長,主要任務是將組員的方案提出來給班委投票確認, 同時統計班委們返回的投票結果,並將結果告訴全部人。

Acceptor:班委,這兒的班委具備投票權,可是班委不關心投票的內容,哈哈哈哈,是否是有點奇怪, 先記住,後面就理解了,班委只關心方案是否是已經被提過,只要這個方案以前沒有被提過就會贊成,將贊成的信息返回給提案的組長。

當組長收到各個班委回覆的信息以後,會統計贊成的人數,若是人數過半(\(\frac{N}{2}+1\)),那麼就會廣播這個提案已經被承認,這時候Learner會在班務本子上記錄下這個提案。

如上圖,有一個組員(Client), 一個組長(Proposer), 三個班委(Acceptor), 兩個Learner,當組員提出方案時,組長會將方案提交給三位班委,班委會看看這個方案以前是否是已經提過(主要是根據方案編號,也就是方案編號一致變化,默認是遞增),沒提過的話會經過這個提案,而後組長統計經過的比例,過半數以後會將方案經過的編號進行廣播,班委會回饋信息,此時Learner會記錄下來同時回饋。

剛剛留下了一個疑惑,爲何開始階段(Prepare(1))時班委不關心內容呢?

在這幾個角色中,Acceptor(班委)是數據庫(其實也不是數據庫,僅僅是爲了方便理解),Learner也是數據庫(備份),當你準備提交一條消息時,第一步僅僅是看能不能與之創建正常的鏈接,其次看看這個數據以前是否是已經提交過,若是大部分均可以創建正常的鏈接而且沒有被提交過,那麼說明咱們的數據就能夠提交了。

Paxos活鎖

前面說過,三個班委(Acceptor)只要接受到的提案是未提交的且過半的話,就會經過,若是一個提案1的組長Proposer正在投票信息準備通知時,另外一個組長Proposer又提交了提案2,那麼班委就會開始討論提案2, 放棄提案1的討論,此時提案1被丟棄,那組長1會將提案從新提交,這致使了死鎖的誕生,爲了解決這個問題,可讓提交方案的組長隨機睡眠一段時間。

Paxos改進版

前面例子能夠看出是一個兩階段提交的過程, 改進版最主要的點在於,在Acceptor中選出一個主節點,要提交議案直接交給主節點,由主節點將這些消息同步給其餘節點,若是此時過半數,那麼久將數據提交,而後將信息返回給提議員(組長),什麼意思呢,就是組長提交方案以後,交給班委的頭目,班委頭目統計好投票結果,若是經過了直接通知全部班委以及記錄員,同時將信息返回給提議員(也就是組長)。

主節點的選舉

對於三個班委(Acceptor)而言,有一個時間週期,若是這個週期內收到主節點的心跳包,那麼就會相安無事,若是週期內沒收到心跳包,那麼就會向其餘節點發出請求包,這個包主要是本身要當主節點,請你們投票,全部接受到這個請求包的節點,回覆贊成,當一個節點收到的贊成信息過半以後,就會成爲主節點,同時廣播這個信息,收到信息的節點就成爲了從節點。

全部有關操做都會經過這個主節點,主節點再在其他的節點之間進行投票,經過以後主節點直接提交事務而後將信息返回給調用者。

Paxos與數據提交

簡單說來,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,其它的算法都是殘次品。

咱們還能夠看到:對於同一個值的在不一樣結點的修改提案就算是在接收方被亂序收到也是沒有問題的。

商業產品

這兒主要了解GTS、LCN、TXC,另外還有上一篇文章講過的TCC,這兒就不繼續重複了。

GTS

GTS是目前業界第一款,也是惟一的一款通用的解決微服務分佈式事務問題的中間件,並且能夠保證數據的強一致性。本文將對GTS簡單概述,詳情能夠參考阿里巴巴官方文檔介紹。

GTS是一款分佈式事務中間件,由阿里巴巴中間件部門研發,能夠爲微服務架構中的分佈式事務提供一站式解決方案。GTS方案的基本思路是:將分佈式事務與具體業務分離,在平臺層面開發通用的事務中間件GTS,由事務中間件協調各服務的調用一致性,負責分佈式事務的生命週期管理、服務調用失敗的自動回滾。

GTS方案有三方面的優點:
第一、它將微服務從分佈式事務中解放出來,微服務的實現不須要再考慮反向接口、冪等、回滾策略等複雜問題,只須要業務本身的接口便可,大大下降了微服務開發的難度與工做量。將分佈式事務從所謂的「貴族技術」變爲你們都能使用的「平民技術 」,有利於微服務的落地與推廣。
第二、GTS對業務代碼幾乎沒有侵入,只須要經過註解@TxcTransaction界定事務邊界便可,微服務接入GTS的成本很是低。
第三、性能方面GTS也很是優秀,是傳統XA方案的8~10倍。

GTS原理

GTS中間件主要包括客戶端(GTS Client)、資源管理器(GTS RM)和事務協調器(GTS Server)三部分。GTS Client主要完成事務的發起與結束。GTS RM完成分支事務的開啓、提交、回滾等操做。GTS Server主要負責分佈式事務的總體推動,事務生命週期的管理。

GTS和微服務集成後的結構圖如上圖所示。GTS Client須要和業務應用集成部署,RM與微服務集成部署。當業務應用發起服務調用時,首先會經過GTS Client向TC註冊新的全局事務。以後GTS Server會給業務應用返回全局惟一的事務編號xid。業務應用調用服務時會將xid傳播到服務端。微服務在執行數據庫操做時會經過GTS RM向GTS Server註冊分支事務,並完成分支事務的提交。若是A、B、C三個服務均調用成功,GTS Client會通知GTS Server結束事務。假設C調用失敗,GTS Client會要求GTS Server發起全局回滾。而後由各自的RM完成回滾工做。

LCN

TX-LCN定位是於一款事務協調性框架,框架本事並不操做事務,而是基於對事務的協調從而達到事務一致性的效果。TX-LCN由兩大模塊組成, TxClient、TxManager,TxClient做爲模塊的依賴框架,提供TX-LCN的標準支持,TxManager做爲分佈式事務的控制放。事務發起方或者參與反都由TxClient端來控制。

下圖來自LCN官網,與LCN有關詳情能夠訪問官方倉庫

核心的步驟

  • 建立事務組,是指在事務發起方開始執行業務代碼以前先調用TxManager建立事務組對象,而後拿到事務標示GroupId的過程。
  • 加入事務組,添加事務組是指參與方在執行完業務方法之後,將該模塊的事務信息通知給TxManager的操做。
  • 通知事務組,是指在發起方執行完業務代碼之後,將發起方執行結果狀態通知給TxManager,TxManager將根據事務最終狀態和事務組的信息來通知相應的參與模塊提交或回滾事務,並返回結果給事務發起方。

LCN事務模式

LCN主要有三種事務模式,分別是LCN模式、TCC模式、TXC模式。

LCN模式

原理:

LCN模式是經過代理Connection的方式實現對本地事務的操做,而後在由TxManager統一協調控制事務。當本地事務提交回滾或者關閉鏈接時將會執行假操做,該代理的鏈接將由LCN鏈接池管理。

特色:

  • 該模式對代碼的嵌入性爲低。
  • 該模式僅限於本地存在鏈接對象且可經過鏈接對象控制事務的模塊。
  • 該模式下的事務提交與回滾是由本地事務方控制,對於數據一致性上有較高的保障。
  • 該模式缺陷在於代理的鏈接須要隨事務發起方一共釋放鏈接,增長了鏈接佔用的時間。

TCC模式

原理:

TCC事務機制相對於傳統事務機制(X/Open XA Two-Phase-Commit),其特徵在於它不依賴資源管理器(RM)對XA的支持,而是經過對(由業務系統提供的)業務邏輯的調度來實現分佈式事務。主要由三步操做,Try: 嘗試執行業務、 Confirm:確認執行業務、 Cancel: 取消執行業務。

特色:

  • 該模式對代碼的嵌入性高,要求每一個業務須要寫三種步驟的操做。
  • 該模式對有無本地事務控制均可以支持使用面廣。
  • 數據一致性控制幾乎徹底由開發者控制,對業務開發難度要求高。

TXC模式

原理:

TXC模式命名來源於淘寶,實現原理是在執行SQL以前,先查詢SQL的影響數據,而後保存執行的SQL快走信息和建立鎖。當須要回滾的時候就採用這些記錄數據回滾數據庫,目前鎖實現依賴redis分佈式鎖控制。

特色:

  • 該模式一樣對代碼的嵌入性低。
  • 該模式僅限於對支持SQL方式的模塊支持。
  • 該模式因爲每次執行SQL以前須要先查詢影響數據,所以相比LCN模式消耗資源與時間要多。
  • 該模式不會佔用數據庫的鏈接資源。

TXC

TXC(Taobao Transaction Constructor)是阿里巴巴的一個分佈式事務中間件,它能夠經過極少的代碼侵入,實現分佈式事務。

在大部分狀況下,應用只須要引入TXC Client的jar包,進行幾項簡單配置,以及以行計的代碼改造,便可輕鬆保證分佈式數據一致性。TXC同時提供了豐富的編程和配置策略,以適應各類長尾的應用需求。

TXC標準模式(AT模式)

TXC標準模式(Automatic TXC)是最主要的事務模式,經過基於TDDL的TXC數據源,它對SQL語句提供了分佈式事務支持。它幫助應用方以最小的改造代價來實現TDDL下的事務的功能。

在標準模式下,當開啓了TXC分佈式事務時,TXC框架將自動的根據執行的SQL語句,進行事務分支劃分(每一個物理庫上的一個本地事務做爲一個分佈式事務分支),把各個分支統一歸入事務。

分佈式事務的隔離級別能夠配置,讀未提交(read uncommitted)和讀已提交(read committed)。讀未提交是缺省設置。

標準模式適合於TDDL分庫分表、多TDDL數據源、跨進程的多TDDL數據源等幾乎任何TDDL應用場景下的分佈式事務。

TXC自定義模式(MT模式)

MT(Manual TXC)模式,提供用戶能夠介入兩階段提交過程的一種模式。在這種模式下,用戶能夠根據自身業務需求自定義在TXC的兩階段中每一個階段的具體行爲。MT模式提供了更多的靈活性,可能性,以達到特殊場景下的自定義優化,及特殊功能的實現。

MT模式不依賴於TDDL,這是它相對於標準模式的一個最大的優點。MT模式幾乎知足任何咱們想到的事務場景。

TXC重試模式

RT(Retry TXC)模式嚴格地說,不屬於傳統的事務範圍。在TXC將其定義爲一種特殊的事務,它經過在用戶指定時間內不停的異步重試失敗的SQL語句,來保證SQL語句最終成功。

RT模式也是基於TXC數據源的。

當咱們經過TDDL執行一個須要分庫的SQL,假設在第一個庫執行成功了,可是在第二個庫執行失敗了。若是採用TXC標準模式,第一個庫的SQL會回滾。對用戶來講,他的SQL失敗了,在兩個庫上是一致的。

若是採用RT模式,第二個庫執行失敗的SQL會保存下來,TXC不斷重試這個SQL,直到成功。對用戶來講, 他的SQL成功了,在兩個庫上最終是一致的。固然,TXC不會一直重試SQL,用戶能夠指定一個超時時間,超過這個時間限制,TXC會發送告警信息到用戶。用戶拿到告警信息後,能夠從業務庫的RT SQL表中拿到對應的SQL語句,決定下一步怎麼處理。

試想一下,當一個SQL涉及到分庫,咱們執行這個SQL失敗了,一般來講,咱們須要經過log查出它在哪幾個庫成功了哪幾個庫失敗了,而且在失敗的庫上不斷重試。這是很繁瑣的。RT模式把用戶從這種繁瑣工做中解脫出來,用戶再也不須要關注哪些庫上SQL失敗了,也不須要本身重試SQL。

相關文章
相關標籤/搜索