分布式系統(tǒng)原理

高可用是指系統(tǒng)無中斷的執(zhí)行功能的能力,代表了系統(tǒng)的可用程度,是進(jìn)行系統(tǒng)設(shè)計(jì)時(shí)必須要遵守的準(zhǔn)則之一。
而高可用的實(shí)現(xiàn)方案,無外乎就是冗余,就存儲(chǔ)的高可用而言,問題不在于如何進(jìn)行數(shù)據(jù)備份,而在于如何規(guī)避數(shù)據(jù)不一致對(duì)業(yè)務(wù)造成的影響。
對(duì)于分布式系統(tǒng)而言,要保證分布式系統(tǒng)中的數(shù)據(jù)一致性就需要一種方案,可以保證數(shù)據(jù)在子系統(tǒng)中始終保持一致,避免業(yè)務(wù)出現(xiàn)問題。
這種實(shí)現(xiàn)方案就叫做分布式事務(wù),要么一起成功,要么一起失敗,必須是一個(gè)整體性的事務(wù)。

1、理論基礎(chǔ)

1.1 CAP

CAP,Consistency Availability Partition tolerance 的簡(jiǎn)寫:

Consistency:一致性,對(duì)某個(gè)客戶端來說,讀操作能夠返回最新的寫操作結(jié)果。
Availability:可用性,非故障節(jié)點(diǎn)在合理的時(shí)間內(nèi)返回合理的響應(yīng)。
Partition tolerance:分區(qū)容錯(cuò)性,分布式系統(tǒng)中系統(tǒng)肯定部署在多臺(tái)機(jī)器上,無法保證網(wǎng)絡(luò)做到 100% 的可靠,所以網(wǎng)絡(luò)分區(qū)一定存在,即 P 一定存在。

在出現(xiàn)網(wǎng)絡(luò)分區(qū)后,就出現(xiàn)了可用性和一致性的問題,我們必須要在這兩者之間進(jìn)行取舍,因此就有了兩種架構(gòu):

  • CP 架構(gòu)
  • AP 架構(gòu)

1.2 BASE理論

BASE 理論指的是基本可用 Basically Available,軟狀態(tài) Soft State,最終一致性 Eventual Consistency,核心思想是即便無法做到強(qiáng)一致性,但應(yīng)該采用適合的方式保證最終一致性。

BASE,Basically Available Soft State Eventual Consistency 的簡(jiǎn)寫:
BA:Basically Available 基本可用,分布式系統(tǒng)在出現(xiàn)故障的時(shí)候,允許損失部分可用性,即保證核心可用。
S:Soft State 軟狀態(tài),允許系統(tǒng)存在中間狀態(tài),而該中間狀態(tài)不會(huì)影響系統(tǒng)整體可用性。
E:Consistency 最終一致性,系統(tǒng)中的所有數(shù)據(jù)副本經(jīng)過一定時(shí)間后,最終能夠達(dá)到一致的狀態(tài)。

BASE 理論本質(zhì)上是對(duì) CAP 理論的延伸,是對(duì) CAP 中 AP 方案的一個(gè)補(bǔ)充。

2、分布式事務(wù)協(xié)議

2.1 二階段提交協(xié)議:2PC

2.1.1 概述

二階段提交(Two-phase Commit),是指,為了使基于分布式系統(tǒng)架構(gòu)下的所有節(jié)點(diǎn)在進(jìn)行事務(wù)提交時(shí)保持一致性而設(shè)計(jì)的一種算法(Algorithm)。通常,二階段提交也被稱為是一種協(xié)議(Protocol)。

在分布式系統(tǒng)中,每個(gè)節(jié)點(diǎn)雖然可以知曉自己的操作是成功或者失敗,卻無法知道其他節(jié)點(diǎn)的操作是成功或失敗。

當(dāng)一個(gè)事務(wù)跨越多個(gè)節(jié)點(diǎn)時(shí),為了保持事務(wù)的 ACID 特性,需要引入一個(gè)作為協(xié)調(diào)者的組件來統(tǒng)一掌控所有節(jié)點(diǎn)(稱作參與者)的操作結(jié)果并最終指示這些節(jié)點(diǎn)是否要把操作結(jié)果進(jìn)行真正的提交(比如將更新后的數(shù)據(jù)寫入磁盤等等)。

因此,二階段提交的算法思路可以概括為:參與者將操作成敗通知協(xié)調(diào)者,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情報(bào)決定各參與者是否要提交操作還是中止操作。

2.1.2 二階段提交過程
  • 投票階段
image.png

投票階段執(zhí)行流程:

  1. 協(xié)調(diào)者向所有參與者詢問是否可以執(zhí)行提交操作,并開始等待各參與者的響應(yīng)。
  2. 參與者執(zhí)行事務(wù)操作,如果執(zhí)行成功就返回 Yes 響應(yīng),如果執(zhí)行失敗就返回 No 響應(yīng)。
  3. 如果協(xié)調(diào)者接受參與者響應(yīng)超時(shí),也會(huì)認(rèn)為執(zhí)行事務(wù)操作失敗。
  • 提交階段
image.png

提交階段執(zhí)行流程:

  1. 如果第一階段匯總所有參與者都返回 Yes 響應(yīng),協(xié)調(diào)者向所有參與者發(fā)出提交請(qǐng)求,所有參與者提交事務(wù)。
  2. 如果第一階段中有一個(gè)或者多個(gè)參與者返回 No 響應(yīng),協(xié)調(diào)者向所有參與者發(fā)出回滾請(qǐng)求,所有參與者進(jìn)行回滾操作。
2.1.3 優(yōu)缺點(diǎn)
  • 優(yōu)點(diǎn)
    盡量保證了數(shù)據(jù)的強(qiáng)一致,但不是 100% 一致

  • 缺點(diǎn)

    1. 單點(diǎn)故障,由于協(xié)調(diào)者的重要性,一旦協(xié)調(diào)者發(fā)生故障,參與者會(huì)一直阻塞,尤其是在第二階段,協(xié)調(diào)者發(fā)生故障,那么所有的參與者都處于鎖定事務(wù)資源的狀態(tài)中,而無法繼續(xù)完成事務(wù)操作。
    2. 同步阻塞,由于所有節(jié)點(diǎn)在執(zhí)行操作時(shí)都是同步阻塞的,當(dāng)參與者占有公共資源時(shí),其他第三方節(jié)點(diǎn)訪問公共資源不得不處于阻塞狀態(tài)。
    3. 數(shù)據(jù)不一致,在第二階段中,當(dāng)協(xié)調(diào)者向參與者發(fā)送提交事務(wù)請(qǐng)求之后,發(fā)生了局部網(wǎng)絡(luò)異常或者在發(fā)送提交事務(wù)請(qǐng)求過程中協(xié)調(diào)者發(fā)生了故障,這會(huì)導(dǎo)致只有一部分參與者接收到了提交事務(wù)請(qǐng)求。
      而在這部分參與者接到提交事務(wù)請(qǐng)求之后就會(huì)執(zhí)行提交事務(wù)操作。但是其他部分未接收到提交事務(wù)請(qǐng)求的參與者則無法提交事務(wù)。從而導(dǎo)致分布式系統(tǒng)中的數(shù)據(jù)不一致。

2.2 三階段提交協(xié)議:3PC

2.2.1 概述

三階段提交(Three-phase commit),是為解決兩階段提交協(xié)議的缺點(diǎn)而設(shè)計(jì)的。與兩階段提交不同的是,三階段提交是“非阻塞”協(xié)議。

三階段提交在兩階段提交的第一階段與第二階段之間插入了一個(gè)準(zhǔn)備階段,使得原先在兩階段提交中,參與者在投票之后,由于協(xié)調(diào)者發(fā)生崩潰或錯(cuò)誤,而導(dǎo)致參與者處于無法知曉是否提交或者中止的“不確定狀態(tài)”所產(chǎn)生的可能相當(dāng)長(zhǎng)的延時(shí)的問題得以解決。

2.2.2 三階段提交過程
image.png

詢問階段:CanCommit
協(xié)調(diào)者向參與者發(fā)送 Commit 請(qǐng)求,參與者如果可以提交就返回 Yes 響應(yīng),否則返回 No 響應(yīng)。

準(zhǔn)備階段:PreCommit
協(xié)調(diào)者根據(jù)參與者在詢問階段的響應(yīng)判斷是否執(zhí)行事務(wù)還是中斷事務(wù):
如果所有參與者都返回 Yes,則執(zhí)行事務(wù)。
如果參與者有一個(gè)或多個(gè)參與者返回 No 或者超時(shí),則中斷事務(wù)。
參與者執(zhí)行完操作之后返回 ACK 響應(yīng),同時(shí)開始等待最終指令

提交階段:DoCommit
協(xié)調(diào)者根據(jù)參與者在準(zhǔn)備階段的響應(yīng)判斷是否執(zhí)行事務(wù)還是中斷事務(wù):
如果所有參與者都返回正確的 ACK 響應(yīng),則提交事務(wù)。
如果參與者有一個(gè)或多個(gè)參與者收到錯(cuò)誤的 ACK 響應(yīng)或者超時(shí),則中斷事務(wù)。
如果參與者無法及時(shí)接收到來自協(xié)調(diào)者的提交或者中斷事務(wù)請(qǐng)求時(shí),會(huì)在等待超時(shí)之后,會(huì)繼續(xù)進(jìn)行事務(wù)提交。
協(xié)調(diào)者收到所有參與者的 ACK 響應(yīng),完成事務(wù)。

2.2.3 解決二階段提交時(shí)的問題:

三階段提交解決了二階段提交中存在的由于協(xié)調(diào)者和參與者同時(shí)掛掉可能導(dǎo)致的數(shù)據(jù)一致性問題和單點(diǎn)故障問題,并減少阻塞。
因?yàn)橐坏﹨⑴c者無法及時(shí)收到來自協(xié)調(diào)者的信息之后,他會(huì)默認(rèn)執(zhí)行提交事務(wù)(三階段),而不會(huì)一直持有事務(wù)資源并處于阻塞狀態(tài)(二階段會(huì))。

2.2.4 三階段提交的問題:

在提交階段如果發(fā)送的是中斷事務(wù)請(qǐng)求,但是由于網(wǎng)絡(luò)問題,導(dǎo)致部分參與者沒有接到請(qǐng)求。
那么參與者會(huì)在等待超時(shí)之后執(zhí)行提交事務(wù)操作,這樣這些由于網(wǎng)絡(luò)問題導(dǎo)致提交事務(wù)的參與者的數(shù)據(jù)就與接受到中斷事務(wù)請(qǐng)求的參與者存在數(shù)據(jù)不一致的問題。

所以無論是 2PC 還是 3PC 都不能保證分布式系統(tǒng)中的數(shù)據(jù) 100% 一致。

2.3 ZAB——zookeeper 原子廣播協(xié)議

2.3.1 概述

ZAB 協(xié)議全稱是Zookeeper Atomic Broadcast,是為分布式協(xié)調(diào)服務(wù) Zookeeper 專門設(shè)計(jì)的一種支持 崩潰恢復(fù)原子廣播 協(xié)議。
ZAB 協(xié)議滿足CP,在選舉過程中,是不能對(duì)外提供服務(wù)的。

2.3.3 消息廣播

ZAB 協(xié)議的消息廣播過程(即數(shù)據(jù)同步過程)使用的是一個(gè)原子廣播協(xié)議,類似一個(gè) 二階段提交過程。對(duì)于客戶端發(fā)送的寫請(qǐng)求,全部由 Leader 接收,Leader 將請(qǐng)求封裝成一個(gè)事務(wù) Proposal,將其發(fā)送給所有 Follwer ,然后,根據(jù)所有 Follwer 的反饋,如果超過半數(shù)成功響應(yīng),則執(zhí)行 commit 操作(先提交自己,再發(fā)送 commit 給所有 Follwer)。

廣播流程

image.png
    1. 客戶端發(fā)起一個(gè)寫操作請(qǐng)求。
    1. Leader 服務(wù)器將客戶端的請(qǐng)求轉(zhuǎn)化為事務(wù) Proposal 提案,同時(shí)為每個(gè) Proposal 分配一個(gè)全局的ID,即zxid。然后將需要廣播的Proposal 依次放到隊(duì)列中,并且根據(jù) FIFO 策略進(jìn)行消息發(fā)送。
    1. Follower 接收到 Proposal 后,會(huì)首先將其以事務(wù)日志的方式寫入本地磁盤中,寫入成功后向 Leader 反饋一個(gè) Ack 響應(yīng)消息。
    1. Leader 接收到超過半數(shù)以上 Follower 的 Ack 響應(yīng)消息后,即認(rèn)為消息發(fā)送成功,可以發(fā)送 commit 消息。
    1. Leader 向所有 Follower 廣播 commit 消息,同時(shí)自身也會(huì)完成事務(wù)提交。Follower 接收到 commit 消息后,會(huì)將上一條事務(wù)提交。

注意:
1、 Leader 服務(wù)器與每一個(gè) Follower 服務(wù)器之間都維護(hù)了一個(gè)單獨(dú)的 FIFO 消息隊(duì)列進(jìn)行收發(fā)消息,使用隊(duì)列消息可以做到異步解耦。 Leader 和 Follower 之間只需要往隊(duì)列中發(fā)消息即可
2、Leader 在收到客戶端請(qǐng)求之后,會(huì)將這個(gè)請(qǐng)求封裝成一個(gè)事務(wù),并給這個(gè)事務(wù)分配一個(gè)全局遞增的唯一 ID,稱為事務(wù)ID(ZXID),ZAB 協(xié)議需要保證事務(wù)的順序,因此必須將每一個(gè)事務(wù)按照 ZXID 進(jìn)行先后排序然后處理
3、可以認(rèn)為這是一種簡(jiǎn)化版本的 2PC,2PC的單點(diǎn)問題(Leader奔潰)這里也會(huì)遇到,ZAB是通過崩潰恢復(fù)來解決的

2.3.3 崩潰恢復(fù)

所謂崩潰恢復(fù),是指當(dāng)leader崩潰(單點(diǎn)故障)后,重新選舉leader并且數(shù)據(jù)保持一致性(數(shù)據(jù)同步)。

  • leader選舉:
    選舉是通過投票來的,主要分為以下幾個(gè)階段,
  1. 變更狀態(tài):Leader掛后,余下的Flower服務(wù)器都會(huì)將自己的服務(wù)器狀態(tài)變更為L(zhǎng)OOKING,然后再開始進(jìn)入Leader選舉過程;

  2. 發(fā)起投票:首輪投票,每個(gè)節(jié)點(diǎn)發(fā)出一個(gè)投票,先投票給自己,然后再把投票結(jié)果廣播到集群中別的節(jié)點(diǎn),其他機(jī)器。投票內(nèi)容包含節(jié)點(diǎn)的myid(zookeeper安裝時(shí)要設(shè)置的值,表示當(dāng)前節(jié)點(diǎn)id)和zxid(事務(wù)id),比如ZK1的投票為(1, 0),ZK2的投票為(2, 0)

  3. 驗(yàn)證投票:每個(gè)節(jié)點(diǎn)都投票給自己并且廣播之后,那么節(jié)點(diǎn)就會(huì)收到別的節(jié)點(diǎn)的投票結(jié)果,在收到投票后可以驗(yàn)證投票的有效性,如檢查是否是本輪投票、是否來自LOOKING狀態(tài)的服務(wù)器,

  4. 變更投票:驗(yàn)證完收到的投票結(jié)果后,處理投票,針對(duì)每一個(gè)投票,服務(wù)器都需要將別人的投票和自己的投票進(jìn)行比較,規(guī)則如下
    · 優(yōu)先檢查ZXID。ZXID比較大的服務(wù)器優(yōu)先作為L(zhǎng)eader;
    · 如果ZXID相同,那么就比較myid。myid較大的服務(wù)器作為L(zhǎng)eader服務(wù)器;

  5. 統(tǒng)計(jì)投票:根據(jù)以上規(guī)則變更自己的投票,然后廣播第二輪投票,還是同樣的過程,先驗(yàn)證投票,然后變更投票,變更完成以后統(tǒng)計(jì)票倉(cāng)(本輪投票過程中接收到的別的節(jié)點(diǎn)的投票信息)中,是否有超過半數(shù)的相同投票,如果有,則其就是新的leader,選舉結(jié)束;如果沒有,則繼續(xù)發(fā)起投票,知道選出leader。

  6. **改變服務(wù)器狀態(tài) **:選出leader后,變更各服務(wù)器狀態(tài),leader從LOOKING變成Leader,別的機(jī)器變成Flower,然后同步leader數(shù)據(jù)。

image.png

由上面規(guī)則可知,通常那臺(tái)服務(wù)器上的數(shù)據(jù)越新(ZXID會(huì)越大),其成為L(zhǎng)eader的可能性越大,也就越能夠保證數(shù)據(jù)的恢復(fù)。如果ZXID相同,則SID越大機(jī)會(huì)越大。

  • 數(shù)據(jù)同步:
    上面的leader選舉結(jié)束后,只有當(dāng)新的leader和follower同步數(shù)據(jù)之后,才能對(duì)外提供服務(wù)。
    同步分為以下幾個(gè)階段:
  1. 所有follower上報(bào)自己最后接收的事務(wù)的任期epoch(每個(gè)Proposal都包含了一個(gè)epoch值,用來代表當(dāng)前的Leader 周期);leader比較所有的任期,選取最大的epoch,加1后作為當(dāng)前的任期E=E+1,并且將任期epoch廣播給所有follower;follower將任期改為leader發(fā)過來的值之后,返回給leader當(dāng)前follewer節(jié)點(diǎn)上的事務(wù)隊(duì)列L;

  2. leader從隊(duì)列集合中選取任期最大的隊(duì)列,如果有多個(gè)隊(duì)列任期都是最大,則選取事務(wù)編號(hào)n最大的隊(duì)列Lmax(通常就是leader節(jié)點(diǎn)自己的事務(wù)隊(duì)列,因?yàn)檫x舉leader時(shí),就是選出的事務(wù)zxid最大的節(jié)點(diǎn)),并將其廣播給各個(gè)follower,follower接收隊(duì)列替換自己的事務(wù)隊(duì)列,并且執(zhí)行隊(duì)列中的事務(wù)(執(zhí)行過跳過,未執(zhí)行執(zhí)行),執(zhí)行完以后反饋給leader 表明自己已經(jīng)完成同步(追上來了),leader 收到過半反饋后,發(fā)送commit 消息;follower 接收到commit 消息后,提交事務(wù);
    至此各個(gè)節(jié)點(diǎn)的數(shù)據(jù)達(dá)成一致,zookeeper恢復(fù)正常服務(wù)。

注意:在zk選舉中,通過投票已經(jīng)確認(rèn)leader服務(wù)器是最大的zxid的節(jié)點(diǎn)了,所以同步過程沒有那么復(fù)雜。
同步階段主要是利用 Leader 前一階段獲得的最新 Proposal 歷史,同步集群中所有的副本。只有當(dāng)超過半數(shù)的節(jié)點(diǎn)都同步完成,準(zhǔn) Leader 才會(huì)成為真正的 Leader。Follower 只會(huì)處理 zxid 比自己 lastZxid 大的 Proposal。

3、最終一致性分布式事務(wù)方案

3.1 本地消息表

本地消息表的核心思想是將分布式事務(wù)拆分成本地事務(wù)進(jìn)行處理。

例如,在訂單系統(tǒng)新增一條消息表,將新增訂單和新增消息放到一個(gè)事務(wù)里完成,然后通過輪詢的方式去查詢消息表,將消息推送到 MQ,庫(kù)存系統(tǒng)去消費(fèi) MQ。

image.png
執(zhí)行流程:
  1. 訂單系統(tǒng),添加一條訂單和一條消息,在一個(gè)事務(wù)里提交。

  2. 訂單系統(tǒng),使用定時(shí)任務(wù)輪詢查詢狀態(tài)為未同步的消息表,發(fā)送到 MQ,如果發(fā)送失敗,就重試發(fā)送。

  3. 庫(kù)存系統(tǒng),接收 MQ 消息,修改庫(kù)存表,需要保證冪等操作。

  4. 如果修改成功,調(diào)用 RPC 接口修改訂單系統(tǒng)消息表的狀態(tài)為已完成或者直接刪除這條消息。
    如果修改失敗,可以不做處理,等待重試。

訂單系統(tǒng)中的消息有可能由于業(yè)務(wù)問題會(huì)一直重復(fù)發(fā)送,所以為了避免這種情況可以記錄一下發(fā)送次數(shù),當(dāng)達(dá)到次數(shù)限制之后報(bào)警,人工接入處理;庫(kù)存系統(tǒng)需要保證冪等,避免同一條消息被多次消費(fèi)造成數(shù)據(jù)一致。

本地消息表這種方案實(shí)現(xiàn)了最終一致性,需要在業(yè)務(wù)系統(tǒng)里增加消息表,業(yè)務(wù)邏輯中多一次插入的 DB 操作,所以性能會(huì)有損耗,而且最終一致性的間隔主要由定時(shí)任務(wù)的間隔時(shí)間決定。

3.2 MQ 消息事務(wù)

消息事務(wù)的原理是將兩個(gè)事務(wù)通過消息中間件進(jìn)行異步解耦。

image.png

從上面可以看出,消息事務(wù)一定要保證業(yè)務(wù)操作與消息發(fā)送的一致性,如果業(yè)務(wù)操作成功,這條消息也一定投遞成功。

消息事務(wù)依賴于消息中間件的事務(wù)消息,基于消息中間件的二階段提交實(shí)現(xiàn)的,RocketMQ 就支持事務(wù)消息。RabbitMQ也支持事務(wù)消息

執(zhí)行流程:
  1. 發(fā)送 Prepare 消息到消息中間件。
  2. 發(fā)送成功后,執(zhí)行本地事務(wù)。
  3. 如果事務(wù)執(zhí)行成功,則 Commit,消息中間件將消息下發(fā)至消費(fèi)端。
  4. 如果事務(wù)執(zhí)行失敗,則回滾,消息中間件將這條 Prepare 消息刪除。
  5. 消費(fèi)端接收到消息進(jìn)行消費(fèi),如果消費(fèi)失敗,則不斷重試。

這種方案也是實(shí)現(xiàn)了最終一致性,對(duì)比本地消息表實(shí)現(xiàn)方案,不需要再建消息表,不再依賴本地?cái)?shù)據(jù)庫(kù)事務(wù)了,所以這種方案更適用于高并發(fā)的場(chǎng)景。

3.3 最大努力通知

最大努力通知相比前兩種方案實(shí)現(xiàn)簡(jiǎn)單,適用于一些最終一致性要求較低的業(yè)務(wù),比如支付通知,短信通知這種業(yè)務(wù)。
以支付通知為例,業(yè)務(wù)系統(tǒng)調(diào)用支付平臺(tái)進(jìn)行支付,支付平臺(tái)進(jìn)行支付,進(jìn)行操作支付之后支付平臺(tái)會(huì)盡量去通知業(yè)務(wù)系統(tǒng)支付操作是否成功,但是會(huì)有一個(gè)最大通知次數(shù)。
如果超過這個(gè)次數(shù)后還是通知失敗,就不再通知,業(yè)務(wù)系統(tǒng)自行調(diào)用支付平臺(tái)提供一個(gè)查詢接口,供業(yè)務(wù)系統(tǒng)進(jìn)行查詢支付操作是否成功。

image.png
執(zhí)行流程:
  1. 業(yè)務(wù)系統(tǒng)調(diào)用支付平臺(tái)支付接口, 并在本地進(jìn)行記錄,支付狀態(tài)為支付中。
  2. 支付平臺(tái)進(jìn)行支付操作之后,無論成功還是失敗,都需要給業(yè)務(wù)系統(tǒng)一個(gè)結(jié)果通知。
  3. 如果通知一直失敗則根據(jù)重試規(guī)則進(jìn)行重試,達(dá)到最大通知次數(shù)后,不再通知。
  4. 支付平臺(tái)提供查詢訂單支付操作結(jié)果接口。
  5. 業(yè)務(wù)系統(tǒng)根據(jù)一定業(yè)務(wù)規(guī)則去支付平臺(tái)查詢支付結(jié)果。

這種方案也是實(shí)現(xiàn)了最終一致性。

3.4 補(bǔ)償事務(wù) TCC

TCC,Try-Confirm-Cancel 的簡(jiǎn)稱,針對(duì)每個(gè)操作,都需要有一個(gè)其對(duì)應(yīng)的確認(rèn)和取消操作。
當(dāng)操作成功時(shí)調(diào)用確認(rèn)操作,當(dāng)操作失敗時(shí)調(diào)用取消操作,類似于二階段提交,只不過是這里的提交和回滾是針對(duì)業(yè)務(wù)上的,所以基于 TCC 實(shí)現(xiàn)的分布式事務(wù)也可以看做是對(duì)業(yè)務(wù)的一種補(bǔ)償機(jī)制。

3.4.1 TCC 的三個(gè)階段:
  • Try 階段:對(duì)業(yè)務(wù)系統(tǒng)做檢測(cè)及資源預(yù)留、凍結(jié)。

  • Confirm 階段:對(duì)業(yè)務(wù)系統(tǒng)做確認(rèn)提交,Try 階段執(zhí)行成功并開始執(zhí)行 Confirm 階段時(shí),默認(rèn) Confirm 階段是不會(huì)出錯(cuò)的。即:只要 Try 成功,Confirm 一定成功。

  • Cancel 階段:在業(yè)務(wù)執(zhí)行錯(cuò)誤,需要回滾的狀態(tài)下執(zhí)行的業(yè)務(wù)取消,預(yù)留資源釋放。

在 Try 階段,是對(duì)業(yè)務(wù)系統(tǒng)進(jìn)行檢查及資源預(yù)覽,比如訂單和存儲(chǔ)操作,需要檢查庫(kù)存剩余數(shù)量是否夠用,并進(jìn)行預(yù)留,預(yù)留操作的話就是新建一個(gè)可用庫(kù)存數(shù)量字段,Try 階段操作是對(duì)這個(gè)可用庫(kù)存數(shù)量進(jìn)行操作。

3.4.2 TCC執(zhí)行流程:

步驟一(Try 階段):訂單系統(tǒng)將當(dāng)前訂單狀態(tài)設(shè)置為支付中,庫(kù)存系統(tǒng)校驗(yàn)當(dāng)前剩余庫(kù)存數(shù)量是否大于 2,然后將可用庫(kù)存數(shù)量設(shè)置為庫(kù)存剩余數(shù)量 -2,并且設(shè)置凍結(jié)庫(kù)存為2

  • image.png

步驟二(Confirm 階段):如果 Try 階段執(zhí)行成功,執(zhí)行 Confirm 階段,將訂單狀態(tài)修改為支付成功,庫(kù)存剩余數(shù)量修改為可用庫(kù)存數(shù)量。

  • image.png

步驟三(Cancel 階段):如果 Try 階段執(zhí)行失敗,執(zhí)行 Cancel 階段,將訂單狀態(tài)修改為支付失敗,可用庫(kù)存數(shù)量修改為庫(kù)存剩余數(shù)量。

  • image.png
image.png
3.4.3 基于 TCC 實(shí)現(xiàn)的分布式事務(wù)框架:

ByteTCC,github.com/liuyangming
tcc-transaction:github.com/changmingxi

參考:https://mp.weixin.qq.com/s/Rowg-rEQZnaSaupJ9Q7kJw

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,224評(píng)論 6 529
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,916評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,014評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,466評(píng)論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,245評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,795評(píng)論 1 320
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,869評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,010評(píng)論 0 285
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,524評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,487評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,634評(píng)論 1 366
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,173評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,884評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,282評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,541評(píng)論 1 281
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,236評(píng)論 3 388
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,623評(píng)論 2 370