分布式相關(guān)理論和分布式事務(wù)

原文地址: https://blog.wangriyu.wang/2018/06-Distribution.html

簡書上傳不了 svg 格式的圖片嗎?! 圖文可以去原文看 ??

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

CAP 定理

CAP 定理指出對(duì)于一個(gè)分布式系統(tǒng)來說,不可能同時(shí)滿足以下三點(diǎn):

  • 一致性 (Consistence): 等同于所有節(jié)點(diǎn)訪問同一份最新的數(shù)據(jù)副本 (強(qiáng)一致性)
  • 可用性 (Availability): 每次請(qǐng)求都能獲取到非錯(cuò)的響應(yīng),但是不保證獲取的數(shù)據(jù)為最新數(shù)據(jù)
  • 分區(qū)容錯(cuò)性 (Partition tolerance): 系統(tǒng)如果不能在時(shí)限內(nèi)達(dá)成數(shù)據(jù)一致性,就意味著發(fā)生了分區(qū)的情況,此時(shí)必須在 C 和 A 之間做出取舍

一個(gè)分布式系統(tǒng)里面,節(jié)點(diǎn)組成的網(wǎng)絡(luò)本來應(yīng)該是連通的。然而可能因?yàn)橐恍┕收匣蛘哐訒r(shí),使得有些節(jié)點(diǎn)之間不連通了,整個(gè)網(wǎng)絡(luò)就分成了幾塊區(qū)域。數(shù)據(jù)就散布在了這些不連通的區(qū)域中,這就叫分區(qū)。當(dāng)你一個(gè)數(shù)據(jù)項(xiàng)只在一個(gè)節(jié)點(diǎn)中保存,那么分區(qū)出現(xiàn)后,和這個(gè)節(jié)點(diǎn)不連通的部分就訪問不到這個(gè)數(shù)據(jù)了。這時(shí)分區(qū)就是無法容忍的。提高分區(qū)容忍性的辦法就是將一個(gè)數(shù)據(jù)項(xiàng)復(fù)制到多個(gè)節(jié)點(diǎn)上,那么出現(xiàn)分區(qū)之后,這一數(shù)據(jù)項(xiàng)就可能分布到各個(gè)區(qū)里,容忍性就提高了。然而,要把數(shù)據(jù)復(fù)制到多個(gè)節(jié)點(diǎn),就會(huì)帶來一致性的問題,就是多個(gè)節(jié)點(diǎn)上面的數(shù)據(jù)可能是不一致的。要保證一致,每次寫操作就都要等待全部節(jié)點(diǎn)寫成功,而這等待又會(huì)帶來可用性的問題。總的來說就是,數(shù)據(jù)存在的節(jié)點(diǎn)越多,分區(qū)容忍性越高,但要復(fù)制更新的數(shù)據(jù)就越多,一致性就越難保證。為了保證一致性,更新所有節(jié)點(diǎn)數(shù)據(jù)所需要的時(shí)間就越長,可用性就會(huì)降低 -- 來自知乎鄔江的回答

CAP 理論實(shí)際想表達(dá)的是任何分布式系統(tǒng)不能同時(shí)滿足強(qiáng)一致性、高可用性和較好的分區(qū)容錯(cuò)性

[圖片上傳失敗...(image-bb9105-1545273484228)]

RDBMS: Relational Database Management System,關(guān)系型數(shù)據(jù)庫管理系統(tǒng)

由 CAP 定理可知數(shù)據(jù)庫的設(shè)計(jì)需要權(quán)衡取舍,所以可以把數(shù)據(jù)庫大致分為三類:

  • CA: 單點(diǎn)集群,滿足一致性,可用性的系統(tǒng),通常在可擴(kuò)展性上不太強(qiáng)大
  • CP: 滿足一致性,分區(qū)容忍性的系統(tǒng),通常性能不是特別高
  • AP: 滿足可用性,分區(qū)容忍性的系統(tǒng),通常可能對(duì)一致性要求低一些

分布式和集群的區(qū)別:

分布式: 不同的多臺(tái)服務(wù)器上面部署不同的服務(wù)模塊,他們之間通過 Rpc/HTTP 等方式進(jìn)行通信和調(diào)用,對(duì)外提供服務(wù)和組內(nèi)協(xié)作

集群: 不同的多臺(tái)服務(wù)器上面部署相同的服務(wù)模塊,通過分布式調(diào)度軟件進(jìn)行統(tǒng)一的調(diào)度,對(duì)外提供服務(wù)和訪問

ACID 和 BASE

ACID

ACID 指的是傳統(tǒng)數(shù)據(jù)庫中事務(wù)操作所具備的四個(gè)特性:

  • 原子性 (Atomicity): 一個(gè)事務(wù) (transaction) 中的所有操作作為一個(gè)基本單元,要么全部完成,要么全部不完成,不會(huì)結(jié)束在中間某個(gè)環(huán)節(jié)。事務(wù)在執(zhí)行過程中發(fā)生錯(cuò)誤,會(huì)被回滾(Rollback)到事務(wù)開始前的狀態(tài),就像這個(gè)事務(wù)從來沒有執(zhí)行過一樣
  • 一致性 (Consistency): 在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。一個(gè)事務(wù)能夠正確地將數(shù)據(jù)庫從一個(gè)一致性狀態(tài)變換為另一個(gè)一致性狀態(tài)
  • 隔離性 (Isolation): 也可以稱作獨(dú)立性,數(shù)據(jù)庫允許多個(gè)并發(fā)事務(wù)同時(shí)對(duì)其數(shù)據(jù)進(jìn)行讀寫和修改的能力,隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。事務(wù)隔離分為不同級(jí)別,包括讀未提交 (Read uncommitted)、讀提交 (read committed)、可重復(fù)讀 (repeatable read) 和串行化 (Serializable)
  • 持久性 (Durability): 事務(wù)處理結(jié)束后,對(duì)數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會(huì)丟失

BASE

BASE 理論是對(duì) CAP 理論的延伸,核心思想是雖然無法做到強(qiáng)一致性 (Strong Consistency),但可以采用適合的方式達(dá)到最終一致性 (Eventual Consitency)

BASE 包含三部分:

  • 基本可用 (Basically Available): 指分布式系統(tǒng)在出現(xiàn)故障的時(shí)候,允許損失部分可用性,保證核心可用
  • 軟狀態(tài) (Soft State): 指允許系統(tǒng)存在中間狀態(tài),而該中間狀態(tài)不會(huì)影響系統(tǒng)整體可用性。分布式存儲(chǔ)中一般一份數(shù)據(jù)至少會(huì)有三個(gè)副本,允許不同節(jié)點(diǎn)間副本同步的延時(shí)就是軟狀態(tài)的體現(xiàn)。mysql replication 的異步復(fù)制也是一種體現(xiàn)
  • 最終一致性 (Eventual Consistency): 指系統(tǒng)中的所有數(shù)據(jù)副本經(jīng)過一定時(shí)間后,最終能夠達(dá)到一致的狀態(tài)。最終一致性是弱一致性的一種特殊情況

兩者區(qū)別

ACID 隸屬于 CA,是傳統(tǒng)數(shù)據(jù)庫常用的設(shè)計(jì)理念,追求強(qiáng)一致性模型

BASE 隸屬于 AP,支持的是大型分布式系統(tǒng),提出通過犧牲強(qiáng)一致性獲得高可用性

但在實(shí)際的分布式場景中,不同業(yè)務(wù)單元和組件對(duì)數(shù)據(jù)一致性的要求是不同的,因此在具體的分布式系統(tǒng)架構(gòu)設(shè)計(jì)過程中,ACID 特性與 BASE 理論往往會(huì)結(jié)合在一起使用。比如整體滿足 BASE,局部滿足 ACID。

一致性模型

  • 強(qiáng)一致性: 當(dāng)更新操作完成之后,任何多個(gè)后續(xù)進(jìn)程或者線程的訪問都會(huì)返回最新的更新過的值。這種是對(duì)用戶最友好的,就是用戶上一次寫什么,下一次就保證能讀到什么。但是這種實(shí)現(xiàn)對(duì)性能影響較大,因?yàn)檫@意味著,只要上次的操作沒有處理完,就不能讓用戶讀取數(shù)據(jù)
  • 弱一致性: 系統(tǒng)并不保證進(jìn)程或者線程的訪問都會(huì)返回最新的更新過的值。系統(tǒng)在數(shù)據(jù)寫入成功之后,不承諾立即可以讀到最新寫入的值,也不會(huì)具體的承諾多久之后可以讀到。但會(huì)盡可能保證在某個(gè)時(shí)間級(jí)別(比如秒級(jí)別)之后,可以讓數(shù)據(jù)達(dá)到一致性狀態(tài)
    • 最終一致性: 弱一致性的特定形式。系統(tǒng)保證在沒有后續(xù)更新的前提下,系統(tǒng)最終返回上一次更新操作的值。在沒有故障發(fā)生的前提下,不一致窗口的時(shí)間主要受通信延遲,系統(tǒng)負(fù)載和復(fù)制副本的個(gè)數(shù)影響。DNS 是一個(gè)典型的最終一致性系統(tǒng)
      • 因果一致性: 如果 A 進(jìn)程在更新之后向 B 進(jìn)程通知更新的完成,那么 B 的訪問操作將會(huì)返回更新的值。如果沒有因果關(guān)系的 C 進(jìn)程將會(huì)遵循最終一致性的規(guī)則
      • 讀己所寫一致性: 因果一致性的特定形式。一個(gè)進(jìn)程總可以讀到自己更新的數(shù)據(jù)
      • 會(huì)話一致性: 讀己所寫一致性的特定形式。進(jìn)程在訪問存儲(chǔ)系統(tǒng)同一個(gè)會(huì)話內(nèi),系統(tǒng)保證該進(jìn)程讀己之所寫
      • 單調(diào)讀一致性: 如果一個(gè)進(jìn)程已經(jīng)讀取到一個(gè)特定值,那么該進(jìn)程不會(huì)讀取到該值舊版本的任何值
      • 單調(diào)寫一致性: 系統(tǒng)保證對(duì)同一個(gè)進(jìn)程的寫操作串行化

上述最終一致性的不同方式可以進(jìn)行組合,例如單調(diào)讀一致性和讀己之所寫一致性就可以組合實(shí)現(xiàn)。并且從實(shí)踐的角度來看,這兩者的組合,讀取自己更新的數(shù)據(jù),和一旦讀取到最新的版本不會(huì)再讀取舊版本,對(duì)于此架構(gòu)上的程序開發(fā)來說,會(huì)少很多額外的煩惱。

從服務(wù)端角度,如何盡快將更新后的數(shù)據(jù)分布到整個(gè)系統(tǒng),降低達(dá)到最終一致性的時(shí)間窗口,是提高系統(tǒng)的可用度和用戶體驗(yàn)非常重要的方面。

為了解決分布式的一致性問題,出現(xiàn)了很多一致性協(xié)議和算法,比如二階段提交協(xié)議,三階段提交協(xié)議和 Paxos 算法

FLP 不可能定理

異步通信場景,即使只有一個(gè)進(jìn)程失敗了,也沒有任何算法能保證非失敗進(jìn)程能夠達(dá)到一致性。

異步通信與同步通信的最大區(qū)別是沒有時(shí)鐘、不能時(shí)間同步、不能使用超時(shí)、不能探測失敗、消息可任意延遲、消息可亂序

FLP Impossibility 的證明

分布式事務(wù)

分布式事務(wù)用于在分布式系統(tǒng)中保證不同節(jié)點(diǎn)之間的數(shù)據(jù)一致性,通常會(huì)涉及到多個(gè)數(shù)據(jù)庫。分布式事務(wù)處理的關(guān)鍵是必須有一種方法可以知道事務(wù)在任何地方所做的所有動(dòng)作,提交或回滾事務(wù)的決定必須產(chǎn)生統(tǒng)一的結(jié)果(全部提交或全部回滾)。

DRDA: Distributed Relational Database Architecture,分布式關(guān)系數(shù)據(jù)庫架構(gòu)

XA 規(guī)范

XA 規(guī)范是 X/Open 組織(即現(xiàn)在的 Open Group) 關(guān)于分布式事務(wù)處理 (DTP) 模型的處理規(guī)范。

DTP 模型包括應(yīng)用程序 AP事務(wù)管理器 TM資源管理器 RM通信資源管理器 CRM 四部分。常見的事務(wù)管理器 TM 是交易中間件,常見的資源管理器 RM 是數(shù)據(jù)庫,常見的通信資源管理器 CRM 是消息中間件。交易中間件是必需的,由它通知和協(xié)調(diào)相關(guān)數(shù)據(jù)庫的提交或回滾。

規(guī)范描述了全局的事務(wù)管理器與局部的資源管理器之間的接口。XA 規(guī)范的目的是允許的多個(gè)資源(如數(shù)據(jù)庫,應(yīng)用服務(wù)器,消息隊(duì)列,等等)在同一事務(wù)中訪問,這樣可以使 ACID 屬性跨越應(yīng)用程序而保持有效。

XA 使用兩階段提交或三階段提交來保證所有資源同時(shí)提交或回滾任何特定的事務(wù)

兩階段提交-2PC

當(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)行真正的提交。所以兩階段提交 (Two-phase Commit) 的算法思路可以概括為: 參與者將操作成敗通知協(xié)調(diào)者,再由協(xié)調(diào)者根據(jù)所有參與者的反饋情報(bào)決定各參與者是否要提交操作還是中止操作。

兩階段提交需要的條件:

  1. 分布式系統(tǒng)中,存在一個(gè)節(jié)點(diǎn)作為協(xié)調(diào)者 (Coordinator),其他節(jié)點(diǎn)作為參與者 (Cohorts),且節(jié)點(diǎn)之間可以進(jìn)行網(wǎng)絡(luò)通信
  2. 所有節(jié)點(diǎn)都采用預(yù)寫式日志,且日志被寫入后即被保持在可靠的存儲(chǔ)設(shè)備上,即使節(jié)點(diǎn)損壞不會(huì)導(dǎo)致日志數(shù)據(jù)的消失
  3. 所有節(jié)點(diǎn)不會(huì)永久性損壞,即使損壞后仍然可以恢復(fù)

兩個(gè)階段分別為:

  1. 準(zhǔn)備階段(投票階段)
  2. 提交階段(執(zhí)行階段)

準(zhǔn)備階段

  1. 事務(wù)協(xié)調(diào)者(事務(wù)管理器)給每個(gè)參與者(資源管理器)發(fā)送 Prepare 消息,詢問是否可以執(zhí)行提交操作,并開始等待各參與者節(jié)點(diǎn)的響應(yīng)
  2. 參與者執(zhí)行事務(wù)操作,并將 Undo 信息和 Redo 信息寫入日志
  3. 各參與者節(jié)點(diǎn)響應(yīng)協(xié)調(diào)者節(jié)點(diǎn)發(fā)起的詢問。如果參與者節(jié)點(diǎn)的事務(wù)操作實(shí)際執(zhí)行成功,則它返回一個(gè)"同意" (agreement) 消息;如果參與者節(jié)點(diǎn)的事務(wù)操作實(shí)際執(zhí)行失敗,則它返回一個(gè)"中止" (Abort) 消息

[圖片上傳失敗...(image-41b4a6-1545273484228)]

第一階段也被稱作投票階段,即各參與者投票是否要繼續(xù)接下來的提交操作

提交階段

  • 當(dāng)協(xié)調(diào)者節(jié)點(diǎn)從所有參與者節(jié)點(diǎn)獲得的響應(yīng)消息都為"同意"時(shí)
    1. 協(xié)調(diào)者節(jié)點(diǎn)向所有參與者節(jié)點(diǎn)發(fā)出"正式提交"的請(qǐng)求
    2. 參與者節(jié)點(diǎn)正式完成操作,并釋放在整個(gè)事務(wù)期間內(nèi)占用的資源
    3. 參與者節(jié)點(diǎn)向協(xié)調(diào)者節(jié)點(diǎn)發(fā)送"完成"消息
    4. 協(xié)調(diào)者節(jié)點(diǎn)收到所有參與者節(jié)點(diǎn)反饋的"完成"消息后,完成事務(wù)

[圖片上傳失敗...(image-9f15ac-1545273484228)]

  • 如果任一參與者節(jié)點(diǎn)在第一階段返回的響應(yīng)消息為"中止",或者協(xié)調(diào)者節(jié)點(diǎn)在第一階段的詢問超時(shí)之前無法獲取所有參與者節(jié)點(diǎn)的響應(yīng)消息時(shí)
    1. 協(xié)調(diào)者節(jié)點(diǎn)向所有參與者節(jié)點(diǎn)發(fā)出"回滾操作"的請(qǐng)求
    2. 參與者節(jié)點(diǎn)利用之前寫入的 Undo 信息執(zhí)行回滾,并釋放在整個(gè)事務(wù)期間內(nèi)占用的資源
    3. 參與者節(jié)點(diǎn)向協(xié)調(diào)者節(jié)點(diǎn)發(fā)送"回滾完成"消息
    4. 協(xié)調(diào)者節(jié)點(diǎn)收到所有參與者節(jié)點(diǎn)反饋的"回滾完成"消息后,取消事務(wù)

[圖片上傳失敗...(image-181417-1545273484228)]

不管最后結(jié)果如何,第二階段都會(huì)結(jié)束當(dāng)前事務(wù)

缺陷

1、同步阻塞問題。執(zhí)行過程中,所有參與節(jié)點(diǎn)都是事務(wù)阻塞型的。當(dāng)參與者占有公共資源時(shí),其他第三方節(jié)點(diǎn)訪問公共資源都將處于阻塞狀態(tài)

2、單點(diǎn)故障。由于協(xié)調(diào)者的重要性,一旦協(xié)調(diào)者發(fā)生故障。參與者會(huì)一直阻塞下去。尤其在第二階段,協(xié)調(diào)者發(fā)生故障,那么所有的參與者還都處于鎖定事務(wù)資源的狀態(tài)中,而無法繼續(xù)完成事務(wù)操作。(如果是協(xié)調(diào)者掛掉,可以重新選舉一個(gè)協(xié)調(diào)者,但是無法解決因?yàn)閰f(xié)調(diào)者宕機(jī)導(dǎo)致的參與者處于阻塞狀態(tài)的問題)

3、數(shù)據(jù)不一致。在第二階段中,當(dāng)協(xié)調(diào)者向參與者發(fā)送 commit 請(qǐng)求之后,發(fā)生了局部網(wǎng)絡(luò)異常或者在發(fā)送 commit 請(qǐng)求過程中協(xié)調(diào)者發(fā)生了故障,這會(huì)導(dǎo)致只有一部分參與者接受到了 commit 請(qǐng)求。而在這部分參與者接到 commit 請(qǐng)求之后就會(huì)執(zhí)行 commit 操作。但是其他部分未接到 commit 請(qǐng)求的機(jī)器則無法執(zhí)行事務(wù)提交,于是整個(gè)分布式系統(tǒng)便出現(xiàn)了數(shù)據(jù)不一致的現(xiàn)象

4、二階段提交存在一個(gè)無法解決的問題:

對(duì)于現(xiàn)有模型,可能會(huì)出現(xiàn)的錯(cuò)誤和相應(yīng)的措施如下

  • 協(xié)調(diào)者出錯(cuò),參與者不出錯(cuò)
    • 可以通過快速創(chuàng)建一個(gè)新的協(xié)調(diào)者來解決(或者原本就有備用協(xié)調(diào)者)
  • 協(xié)調(diào)者不出錯(cuò),參與者出錯(cuò)
    • 如果參與者是第一階段一開始就掛了,那么投票失敗,協(xié)調(diào)者取消事務(wù)即可
    • 如果參與者是投完票才掛的,那么投票依舊有效,協(xié)調(diào)者會(huì)下達(dá)最終的事務(wù)操作指令,正常節(jié)點(diǎn)都會(huì)完成最后的事務(wù)提交或回滾,而掛掉的參與者恢復(fù)后只要詢問協(xié)調(diào)者并執(zhí)行相同的操作即可
  • 協(xié)調(diào)者出錯(cuò),參與者也出錯(cuò)
    • 這種情況就比較復(fù)雜了,需要單獨(dú)講

關(guān)于第三個(gè)問題的詳細(xì)描述如下:

[圖片上傳失敗...(image-c43b4a-1545273484228)]

協(xié)調(diào)者掛了,RM3 也掛了,此時(shí)分兩種情況,RM3 是否執(zhí)行了最后的事務(wù)操作:

  • RM3 掛之前不管收沒收到指令,只要沒有執(zhí)行事務(wù)操作,都是不影響最終一致性的,因?yàn)?RM3 掛了但它的事務(wù)尚未作出最后的提交或回滾時(shí),新的協(xié)調(diào)者和其他正常節(jié)點(diǎn)不管最后是做了提交還是回滾,只要 RM3 恢復(fù)后詢問新協(xié)調(diào)者采取相同的操作即可保證全局一致
  • 嚴(yán)重的問題是掛掉的 RM3 掛之前執(zhí)行了事務(wù)的最終操作:
    • 協(xié)調(diào)者第二階段發(fā)出一條指令后掛了,而 RM3 收到這條指令后對(duì)事物做了操作后也跟著掛了,等新的協(xié)調(diào)者出現(xiàn)時(shí),沒有人知道之前原協(xié)調(diào)者發(fā)送的是 Commit 還是 Rollback,也不清楚 RM3 是執(zhí)行了提交還是回滾;新的協(xié)調(diào)者出現(xiàn)后會(huì)詢問各節(jié)點(diǎn)狀態(tài),如果有節(jié)點(diǎn)回復(fù)的是 No,那么發(fā)送回滾指令,如果各節(jié)點(diǎn)都回復(fù) Yes,則發(fā)送提交指令;比如上圖中新協(xié)調(diào)者和其他正常節(jié)點(diǎn)應(yīng)該會(huì)投票成功然后執(zhí)行了 Commit 指令,而 RM3 恢復(fù)正常后,整體是否一致很難確定,因?yàn)?RM3 可能在第一階段回復(fù)的是 Abort,然后原協(xié)調(diào)者發(fā)送了 Rollback,掛之前 RM3 已經(jīng)回滾,那么此時(shí)全局就不一致了(此時(shí)需要不一致的 RM3 通過其他方式恢復(fù)一致,但完成之前系統(tǒng)整體是不一致的)

最后這個(gè)問題就是 2PC 無法解決的問題,但 3PC 可以一定程度上解決

三階段提交-3PC

三階段提交 (Three-phase Commit) 是針對(duì)兩階段缺點(diǎn)而設(shè)計(jì)的改進(jìn)型,相比較兩階段提交,做出以下兩點(diǎn)改動(dòng):

  1. 引入超時(shí)機(jī)制。同時(shí)在協(xié)調(diào)者和參與者中都引入超時(shí)機(jī)制(2PC 只有協(xié)調(diào)者設(shè)置了超時(shí)機(jī)制),超時(shí)后可以默認(rèn)執(zhí)行 Commit 或者 Abort,這一點(diǎn)可以避免事務(wù)資源長時(shí)間被阻塞
  2. 在第一階段和第二階段中插入一個(gè)準(zhǔn)備階段。保證了在最后提交階段之前各參與節(jié)點(diǎn)的狀態(tài)是一致的

三個(gè)階段分為:

  1. CanCommit
  2. PreCommit
  3. DoCommit

CanCommit

  1. 協(xié)調(diào)者向參與者發(fā)送 CanCommit 請(qǐng)求。詢問是否可以執(zhí)行事務(wù)提交操作。然后開始等待參與者的響應(yīng)
  2. 參與者接到 CanCommit 請(qǐng)求之后,正常情況下,如果其自身認(rèn)為可以順利執(zhí)行事務(wù),則返回 Yes 響應(yīng),并進(jìn)入預(yù)備狀態(tài)。否則反饋 No

[圖片上傳失敗...(image-1618d1-1545273484228)]

PreCommit

  • 假如協(xié)調(diào)者從所有的參與者獲得的反饋都是 Yes 響應(yīng),那么就會(huì)執(zhí)行事務(wù)的預(yù)執(zhí)行:
    1. 發(fā)送預(yù)提交請(qǐng)求協(xié)調(diào)者向參與者發(fā)送 PreCommit 請(qǐng)求,并進(jìn)入 Prepared 階段
    2. 事務(wù)預(yù)提交參與者接收到 PreCommit 請(qǐng)求后,會(huì)執(zhí)行事務(wù)操作,并將 Undo 和 Redo 信息記錄到事務(wù)日志中
    3. 如果參與者成功的執(zhí)行了事務(wù)操作,則返回 ACK 響應(yīng),同時(shí)開始等待最終指令

[圖片上傳失敗...(image-7bd5b9-1545273484228)]

此圖中如果某條 PreCommit 消息未到達(dá)或者超時(shí),RM 應(yīng)該中斷自己本地的事務(wù),就跟下圖中 Abort 超時(shí)一樣

  • 假如有任何一個(gè)參與者向協(xié)調(diào)者發(fā)送了 No 響應(yīng),或者等待超時(shí)之后,協(xié)調(diào)者都沒有接到參與者的響應(yīng),那么就執(zhí)行事務(wù)的中斷:
    1. 發(fā)送中斷請(qǐng)求協(xié)調(diào)者向所有參與者發(fā)送 Abort 請(qǐng)求
    2. 參與者收到來自協(xié)調(diào)者的 Abort 請(qǐng)求之后(或超時(shí)之后,仍未收到協(xié)調(diào)者的請(qǐng)求),執(zhí)行事務(wù)的中斷

[圖片上傳失敗...(image-ea0c4f-1545273484228)]

DoCommit

根據(jù)情況分為兩種情形:

  • 正常響應(yīng)后執(zhí)行提交操作完成事務(wù):
    1. 協(xié)調(diào)者接收到 PreCommit 階段中參與者發(fā)送的 ACK 響應(yīng),那么他將從預(yù)提交狀態(tài)進(jìn)入到提交狀態(tài),并向所有參與者發(fā)送 DoCommit 請(qǐng)求
    2. 參與者接收到 DoCommit 請(qǐng)求之后,執(zhí)行正式的事務(wù)提交,并在完成事務(wù)提交之后釋放所有事務(wù)資源
    3. 事務(wù)提交完之后,向協(xié)調(diào)者發(fā)送 ACK 響應(yīng)
    4. 協(xié)調(diào)者接收到所有參與者的 ACK 響應(yīng)之后,完成事務(wù)

[圖片上傳失敗...(image-508d8f-1545273484228)]

  • 協(xié)調(diào)者沒有接收到參與者發(fā)送的 ACK 響應(yīng)(可能是接受者發(fā)送的不是 ACK 響應(yīng),也可能響應(yīng)超時(shí)),那么就會(huì)執(zhí)行中斷事務(wù):
    1. 協(xié)調(diào)者向所有參與者發(fā)送 Abort 請(qǐng)求
    2. 參與者接收到 Abort 請(qǐng)求之后,利用其在階段二記錄的 Undo 信息來執(zhí)行事務(wù)的回滾操作,并在完成回滾之后釋放所有的事務(wù)資源。
    3. 參與者完成事務(wù)回滾之后,向協(xié)調(diào)者發(fā)送 ACK 消息
    4. 協(xié)調(diào)者接收到參與者反饋的 ACK 消息之后,結(jié)束事務(wù)

[圖片上傳失敗...(image-8ad1fa-1545273484228)]

圖中 RM3 在第二階段未正常響應(yīng) ACK,可能有如下情況:

  • 比如 RM3 未正常接收 PreCommit 消息,在第二階段就取消了本地事務(wù),所以沒有返回 ACK,則第三階段接收 Abort 時(shí)并不需要做什么
  • 也可能是 RM3 收到了 PreCommit 消息并執(zhí)行了事務(wù)操作,但是 ACK 消息發(fā)送超時(shí),則第三階段接收 Abort 時(shí)也是同其他節(jié)點(diǎn)一樣執(zhí)行 Undo 回滾
  • 如果是第二階段 RM3 掛了,如果是持久性掛了,那就掛了吧,現(xiàn)階段就不管它了,等恢復(fù)了再做數(shù)據(jù)同步;如果掛了之后又恢復(fù)了,需要詢問 TM 現(xiàn)在的事務(wù)狀態(tài)來進(jìn)行判斷是否取消本地事務(wù)還是繼續(xù)完成事務(wù)

在第三階段,如果參與者無法及時(shí)接收到來自協(xié)調(diào)者的 DoCommit 或者 Abort 請(qǐng)求時(shí),會(huì)在等待超時(shí)之后,會(huì)繼續(xù)進(jìn)行事務(wù)的提交

這么做是有一定考究的,因?yàn)槟苓M(jìn)入第三階段,說明協(xié)調(diào)者肯定在第二階段發(fā)起了 PreCommit 請(qǐng)求,而發(fā)起 PreCommit 請(qǐng)求的前提是第一階段所有參與者都響應(yīng)了 Yes,這表明所有參與者當(dāng)時(shí)的狀態(tài)都是樂觀的,那么第三階段參與者就算沒有按時(shí)收到來自協(xié)調(diào)者的 DoCommit 請(qǐng)求,也繼續(xù)完成本地事務(wù)的提交,這樣完成全局事務(wù)的可能性還是很大的,這一點(diǎn)是針對(duì) 2PC 數(shù)據(jù)不一致問題的

但是這一點(diǎn)也會(huì)造成 3PC 的一致性缺陷: 如果此時(shí)是協(xié)調(diào)者對(duì)某個(gè) RM 發(fā)出的 Abort 請(qǐng)求超時(shí),而那個(gè) RM 繼續(xù)完成本地事務(wù)的提交,這就會(huì)造成與其他進(jìn)行回滾操作的節(jié)點(diǎn)數(shù)據(jù)不一致(這種情況概率較小)

缺陷

對(duì)應(yīng) 2PC 的缺陷,我們可以看到 3PC 解決了不少問題,一方面默認(rèn)的超時(shí)機(jī)制可以避免單點(diǎn)故障造成的資源長久阻塞的問題;另一方面狀態(tài)確認(rèn)和默認(rèn)超時(shí)提交也可以解決 2PC 的數(shù)據(jù)不一致問題(雖然這會(huì)造成 3PC 自己的不一致問題,但是因?yàn)?3PC 的機(jī)制,這種概率更小)

至于前面提到的 2PC 無法解決的問題,3PC 又是怎么解決的呢?

我們可以回想 2PC 的問題,沖突的條件就是 RM3 第一階段投了反對(duì)票,而這件事只有原協(xié)調(diào)者知道,掛掉的兩者執(zhí)行了回滾操作,而新協(xié)調(diào)者和正常節(jié)點(diǎn)會(huì)執(zhí)行提交操作;但是 3PC 將準(zhǔn)備階段分為兩步可以確保最終事務(wù)操作之前,大家都知道投票結(jié)果,描述如下:

  • 假如同樣是第二階段協(xié)調(diào)者和 RM3 掛了

[圖片上傳失敗...(image-85e40a-1545273484228)]

其實(shí)只要沒有執(zhí)行事務(wù)最終的提交或者回滾都不影響最終結(jié)果,只要后面 RM3 恢復(fù)后查詢協(xié)調(diào)者并執(zhí)行相同的操作即可

  • 假如是進(jìn)入第三階段協(xié)調(diào)者和 RM3 掛了,而且 RM3 已經(jīng)執(zhí)行了最終操作

[圖片上傳失敗...(image-68f35a-1545273484228)]

這時(shí)候新協(xié)調(diào)者出現(xiàn)后,只要查看正常節(jié)點(diǎn)的狀態(tài)就可以知道發(fā)送提交還是回滾指令: 如果都是 Commited 或者 PreCommit 狀態(tài),說明第一輪投票結(jié)果都是 Yes,否則不可能進(jìn)入 PreCommit 狀態(tài),所以新協(xié)調(diào)者發(fā)送提交指令即可;如果存在節(jié)點(diǎn)的狀態(tài)是 Cancel,說明第一輪投票結(jié)果有反對(duì)票,那么新協(xié)調(diào)者發(fā)送回滾指令即可。可能這里會(huì)有個(gè)疑問,講 DoCommit 的時(shí)候我們說過第二階段參與者的 ACK 可能無法正常響應(yīng)協(xié)調(diào)者,如果是 RM3 第一輪投了支持票后面進(jìn)入 PreCommit 狀態(tài)時(shí)沒有把 ACK 正常響應(yīng)給協(xié)調(diào)者,因此協(xié)調(diào)者發(fā)送了 Abort 指令給 RM3 后掛了,RM3 收到指令后也掛了,此時(shí)還是會(huì)造成 RM3 回滾,而新協(xié)調(diào)者和正常節(jié)點(diǎn)執(zhí)行提交的狀況,這里其實(shí) 3PC 好像也沒法解決,但是這種情況的概率你可以估算一下,本來協(xié)調(diào)者發(fā)送指令掛了然后某些參與者執(zhí)行后也掛了的概率本身就低了,還要滿足掛的協(xié)調(diào)者在投完支持票后響應(yīng)超時(shí)引起協(xié)調(diào)者發(fā)送 Abort 指令的概率,那就更小了

理解 2PC 和 3PC

我們用一個(gè)實(shí)際生活的例子來說明并理解這個(gè)過程:

假設(shè)協(xié)調(diào)者是牧師,而參與者是一男一女,他們來到教堂單獨(dú)跟牧師見面并傳達(dá)是否想跟另一方建立更深的關(guān)系的信息

2PC

第一步男女雙方給牧師遞了小紙條,上面寫著是否想跟另一方建立更深的關(guān)系,并且各自準(zhǔn)備好了信物 (Undo&Redo)

第二步牧師看過之后,如果雙方都寫“是”,那么告知雙方交換信物表示可以繼續(xù)深交;如果有一方寫“否”,那么告知雙方分手吧,信物也撤了吧

但是這里 2PC 無法解決一個(gè)問題: 假如男方寫的紙條信息是“否”,而牧師看過之后先告訴男方你把信物撤了吧,你們不合適,但是牧師緊接著心臟病犯了住院了,而男方收到消息后也撤了信物準(zhǔn)備分手,可是男方突然被人打了住院昏迷;新牧師出現(xiàn),繼續(xù)詢問女方的意見,因?yàn)椴恢滥蟹降囊庖姡麄兛赡軙?huì)促成一樁不美滿的關(guān)系

3PC

第一步男女雙方還是遞了小紙條,表示自己的意愿

第二步牧師看過之后,如果雙方都寫“是”,那么先告知雙方準(zhǔn)備信物;如果有一方寫“否”,那么告知雙方不用準(zhǔn)備信物了;雙方收到消息后再回應(yīng)說自己知道了

第三步牧師確認(rèn)雙方的回應(yīng)后,告知雙方最后是否在一起,是否交換信物

在這里假如第三步牧師也是先告知男方后突發(fā)心臟病住院,而男方也是收到消息后被打昏迷,此時(shí)新牧師出現(xiàn)后可以查看女方是否準(zhǔn)備了信物而完成最后的決定,因?yàn)榧偃缒蟹皆臼遣煌猓敲吹诙诫p方肯定是沒有準(zhǔn)備信物的,而假如男方是同意的,那么雙方肯定是準(zhǔn)備了信物的,那么新牧師可以放心宣布雙方可以在一起

3PC 還對(duì)雙方都引入了超時(shí),2PC 中只有牧師沒收到消息時(shí)會(huì)取消事務(wù),而 3PC 中如果男女雙方長時(shí)間沒有收到牧師消息后也會(huì)執(zhí)行自己的決定,避免了 2PC 中同樣情形時(shí)男女雙方在這里一直耗著(阻塞)而錯(cuò)過了下一任。只不過我們提到了如果第三步牧師是因?yàn)殚L時(shí)間沒有收到男方的消息時(shí)也取消了事務(wù),雖然這時(shí)候男女雙方都是同意的,但是還是會(huì)被取消事務(wù),這也可能造成新的不一致問題,但是相對(duì)來說概率就小得多了

解決不一致問題

通過上述過程可知最后無論是二階段提交還是三階段提交都無法徹底解決分布式的一致性問題,如果系統(tǒng)正常運(yùn)行都能滿足強(qiáng)一致性,但是如果出現(xiàn)意外還是會(huì)導(dǎo)致不一致,不過可以通過其他手段達(dá)到一致性,比如分區(qū)數(shù)據(jù)恢復(fù)或者事務(wù)補(bǔ)償機(jī)制或者采用其他一致性算法

分區(qū)數(shù)據(jù)恢復(fù)

Partition-Recover

復(fù)雜的數(shù)據(jù)恢復(fù)可以參見 SVN 的版本控制,可能可以自動(dòng)合并,也可能會(huì)發(fā)生沖突然后需要人工干預(yù)

簡單的數(shù)據(jù)恢復(fù)可以參見 Mysql 的主從同步,數(shù)據(jù)可以自動(dòng)從主庫導(dǎo)到從庫

合并分區(qū)數(shù)據(jù)達(dá)成一致并不是最困難的,更困難的是處理分區(qū)過程中產(chǎn)生的錯(cuò)誤。當(dāng)分區(qū)操作引起錯(cuò)誤,可以通過事務(wù)補(bǔ)償補(bǔ)救錯(cuò)誤,這可能是人工的也可能是自動(dòng)的

分區(qū)事務(wù)補(bǔ)償

比如 MQ 消息事務(wù)和 TCC 事務(wù)協(xié)議就是一種補(bǔ)償機(jī)制:

  • MQ 事務(wù): 利用消息中間件來異步完成事務(wù)的后一半更新,實(shí)現(xiàn)系統(tǒng)的最終一致性
  • TCC 事務(wù): TCC 是阿里巴巴提出的協(xié)議,將一個(gè)事務(wù)分為 Try、Commit、Cancel 三部分,也可以達(dá)到最終一致性

其他一致性算法

  • Paxos 算法: 一種基于消息傳遞且具有高度容錯(cuò)特性的一致性算法
    • Raft 算法: Raft 是一個(gè)共識(shí)算法,用于取代 Paxos。Raft 的目標(biāo)是提供更好理解的算法,并且證明可以提供與 Paxos 相同的容錯(cuò)性以及性能
    • Zab: Zookeeper atomic broadcast protocol,是 Zookeeper 內(nèi)部用到的一致性協(xié)議。相比 Paxos,Zab 最大的特點(diǎn)是保證強(qiáng)一致性 (strong consistency,或叫線性一致性 linearizable consistency)

Reference

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容