概述
大型業(yè)務(wù)系統(tǒng)有著用戶(hù)多、并發(fā)高的特點(diǎn),而在這方面,集中式數(shù)據(jù)庫(kù)(單機(jī)數(shù)據(jù)庫(kù))的性能很難支持,因此主流的互聯(lián)網(wǎng)公司往往采用分布式(架構(gòu))數(shù)據(jù)庫(kù),物理上利用更多的低端設(shè)備,邏輯上對(duì)大表水平拆分支撐業(yè)務(wù)的需要。
雖然分布式數(shù)據(jù)庫(kù)能解決性能難題,但事務(wù)一致性(Consistency)的問(wèn)題,卻很難在分布式數(shù)據(jù)庫(kù)上得到解決。
數(shù)據(jù)一致性?
一致性問(wèn)題,“萬(wàn)惡之源”是數(shù)據(jù)冗余和分布并通過(guò)網(wǎng)絡(luò)交互+網(wǎng)絡(luò)異常是常態(tài)。
1、數(shù)據(jù)一致性的情形
主庫(kù)、從庫(kù)和緩存數(shù)據(jù)一致性,相同數(shù)據(jù)冗余,關(guān)系數(shù)據(jù)庫(kù),為保證關(guān)據(jù)庫(kù)的高可用和高性能,一般會(huì)采用主從(備)架構(gòu)并引入緩存。其中數(shù)據(jù)不一致性存在于數(shù)據(jù)冗余的時(shí)間窗口內(nèi)。常用的解決方案見(jiàn)數(shù)據(jù)庫(kù)之互聯(lián)網(wǎng)常用架構(gòu)方案。
多副本數(shù)據(jù)之間的數(shù)據(jù)一致性,相同數(shù)據(jù)副本,大數(shù)據(jù)領(lǐng)域,一份數(shù)據(jù)會(huì)有多個(gè)副本并存儲(chǔ)到不同的節(jié)點(diǎn)上??蛻?hù)端可以訪問(wèn)任何一個(gè)節(jié)點(diǎn)進(jìn)行讀寫(xiě)操作。常用的解決方案是基于Paxos、ZAB、Raft、Quorum、Gossip等的開(kāi)源實(shí)現(xiàn)。
分布式服務(wù)之間的數(shù)據(jù)一致性,相關(guān)數(shù)據(jù)分布,分布式服務(wù),不同的服務(wù)操作不同的庫(kù)(表),而且?guī)?表)間要保持一致。常用的解決方案是分布式事務(wù)一致性解決方案。
2、數(shù)據(jù)一致性的概念
強(qiáng)一致性
弱一致性
最終一致性
3、數(shù)據(jù)一致性的原理
ACID
CAP
BASE
4、數(shù)據(jù)一致性的協(xié)議
- 兩階段提交協(xié)議
- 三階段提交協(xié)議
- TCC協(xié)議
- Paxos協(xié)議
- ZAB協(xié)議
- Raft協(xié)議
- Quorum協(xié)議
- Gossip協(xié)議
分布式事務(wù)XA實(shí)現(xiàn)數(shù)據(jù)一致性
所謂分布式服務(wù),就是把之前通過(guò)本地接口交互的模塊,拆分成單獨(dú)的應(yīng)用獨(dú)立部署,并通過(guò)RPC和MQ交互。拿物流中的訂單和庫(kù)存舉例(新增一條訂單記錄,庫(kù)存就要-1),集中式架構(gòu)中,要想保證訂單表和庫(kù)存表的一致性,只要一個(gè)本地事務(wù)(ACID)就能保證兩者的強(qiáng)一致性;而分布式架構(gòu)中,訂單表由訂單服務(wù)操作,庫(kù)存表由庫(kù)存服務(wù)操作。要想保證訂單表和庫(kù)存表的一致性,那么就必須保證訂單服務(wù)對(duì)訂單表的操作和庫(kù)存服務(wù)對(duì)庫(kù)存表的操作同時(shí)成功。之前的一個(gè)本地事務(wù)就變成了一個(gè)分布式事務(wù)。由于服務(wù)之間通過(guò)網(wǎng)絡(luò)交互+網(wǎng)絡(luò)異常是常態(tài),就會(huì)產(chǎn)生服務(wù)間數(shù)據(jù)不一致的情況。這就涉及一個(gè)分布式事務(wù)一致性的問(wèn)題。
如何來(lái)保證分布式事務(wù)的ACID,業(yè)界也有比較成熟的方案,一般是2段提交2PC協(xié)議或者改進(jìn)版也就是3段提交3PC協(xié)議,下面來(lái)分別簡(jiǎn)單介紹下。
2PC協(xié)議也成為2段提交,1prepare階段,2commit階段。
所謂的兩個(gè)階段是指:第一階段:準(zhǔn)備階段(投票階段)和第二階段:提交階段(執(zhí)行階段)。

準(zhǔn)備階段
事務(wù)協(xié)調(diào)者(事務(wù)管理器)給每個(gè)參與者(資源管理器)發(fā)送Prepare消息,每個(gè)參與者要么直接返回失敗(如權(quán)限驗(yàn)證失敗),要么在本地執(zhí)行事務(wù),寫(xiě)本地的redo和undo日志,但不提交,到達(dá)一種“萬(wàn)事俱備,只欠東風(fēng)”的狀態(tài)。
可以進(jìn)一步將準(zhǔn)備階段分為以下三個(gè)步驟:
1)協(xié)調(diào)者節(jié)點(diǎn)向所有參與者節(jié)點(diǎn)詢(xún)問(wèn)是否可以執(zhí)行提交操作(vote),并開(kāi)始等待各參與者節(jié)點(diǎn)的響應(yīng)。
2)參與者節(jié)點(diǎn)執(zhí)行詢(xún)問(wèn)發(fā)起為止的所有事務(wù)操作,并將Undo信息和Redo信息寫(xiě)入日志。(注意:若成功這里其實(shí)每個(gè)參與者已經(jīng)執(zhí)行了事務(wù)操作)
3)各參與者節(jié)點(diǎn)響應(yīng)協(xié)調(diào)者節(jié)點(diǎn)發(fā)起的詢(xún)問(wèn)。如果參與者節(jié)點(diǎn)的事務(wù)操作實(shí)際執(zhí)行成功,則它返回一個(gè)”同意”消息;如果參與者節(jié)點(diǎn)的事務(wù)操作實(shí)際執(zhí)行失敗,則它返回一個(gè)"中止"消息。
提交階段
如果協(xié)調(diào)者收到了參與者的失敗消息或者超時(shí),直接給每個(gè)參與者發(fā)送回滾(Rollback)消息;否則,發(fā)送提交(Commit)消息;參與者根據(jù)協(xié)調(diào)者的指令執(zhí)行提交或者回滾操作,釋放所有事務(wù)處理過(guò)程中使用的鎖資源。(注意:必須在最后階段釋放鎖資源)
接下來(lái)分兩種情況分別討論提交階段的過(guò)程。
當(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ā)出”正式提交(commit)”的請(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ù)。
如果任一參與者節(jié)點(diǎn)在第一階段返回的響應(yīng)消息為”中止”,或者 協(xié)調(diào)者節(jié)點(diǎn)在第一階段的詢(xún)問(wèn)超時(shí)之前無(wú)法獲取所有參與者節(jié)點(diǎn)的響應(yīng)消息時(shí):

1)協(xié)調(diào)者節(jié)點(diǎn)向所有參與者節(jié)點(diǎn)發(fā)出”回滾操作(rollback)”的請(qǐng)求。
2)參與者節(jié)點(diǎn)利用之前寫(xiě)入的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ù)。
不管最后結(jié)果如何,第二階段都會(huì)結(jié)束當(dāng)前事務(wù)。
二階段提交看起來(lái)確實(shí)能夠提供原子性的操作,但是不幸的事,二階段提交還是有幾個(gè)缺點(diǎn)的:
1、同步阻塞問(wèn)題。執(zhí)行過(guò)程中,所有參與節(jié)點(diǎn)都是事務(wù)阻塞型的。當(dāng)參與者占有公共資源時(shí),其他第三方節(jié)點(diǎn)訪問(wèn)公共資源不得不處于阻塞狀態(tài)。
2、單點(diǎn)故障。由于協(xié)調(diào)者的重要性,一旦協(xié)調(diào)者發(fā)生故障。參與者會(huì)一直阻塞下去。尤其在第二階段,協(xié)調(diào)者發(fā)生故障,那么所有的參與者還都處于鎖定事務(wù)資源的狀態(tài)中,而無(wú)法繼續(xù)完成事務(wù)操作。(如果是協(xié)調(diào)者掛掉,可以重新選舉一個(gè)協(xié)調(diào)者,但是無(wú)法解決因?yàn)閰f(xié)調(diào)者宕機(jī)導(dǎo)致的參與者處于阻塞狀態(tài)的問(wèn)題)
3、數(shù)據(jù)不一致。在二階段提交的階段二中,當(dāng)協(xié)調(diào)者向參與者發(fā)送commit請(qǐng)求之后,發(fā)生了局部網(wǎng)絡(luò)異?;蛘咴诎l(fā)送commit請(qǐng)求過(guò)程中協(xié)調(diào)者發(fā)生了故障,這回導(dǎo)致只有一部分參與者接受到了commit請(qǐng)求。而在這部分參與者接到commit請(qǐng)求之后就會(huì)執(zhí)行commit操作。但是其他部分未接到commit請(qǐng)求的機(jī)器則無(wú)法執(zhí)行事務(wù)提交。于是整個(gè)分布式系統(tǒng)便出現(xiàn)了數(shù)據(jù)部一致性的現(xiàn)象。
4、二階段無(wú)法解決的問(wèn)題:協(xié)調(diào)者再發(fā)出commit消息之后宕機(jī),而唯一接收到這條消息的參與者同時(shí)也宕機(jī)了。那么即使協(xié)調(diào)者通過(guò)選舉協(xié)議產(chǎn)生了新的協(xié)調(diào)者,這條事務(wù)的狀態(tài)也是不確定的,沒(méi)人知道事務(wù)是否被已經(jīng)提交。
由于二階段提交存在著諸如同步阻塞、單點(diǎn)問(wèn)題、腦裂等缺陷,所以后來(lái)在二階段提交的基礎(chǔ)上做了改進(jìn),提出了三階段提交。
PC
三階段提交(Three-phase commit),也叫三階段提交協(xié)議(Three-phase commit protocol),是二階段提交(2PC)的改進(jìn)版本。

與兩階段提交不同的是,三階段提交有兩個(gè)改動(dòng)點(diǎn)。
1、引入超時(shí)機(jī)制。同時(shí)在協(xié)調(diào)者和參與者中都引入超時(shí)機(jī)制。
2、在第一階段和第二階段中插入一個(gè)準(zhǔn)備階段。保證了在最后提交階段之前各參與節(jié)點(diǎn)的狀態(tài)是一致的。
也就是說(shuō),除了引入超時(shí)機(jī)制之外,3PC把2PC的準(zhǔn)備階段再次一分為二,這樣三階段提交就有CanCommit、PreCommit、DoCommit三個(gè)階段。
CanCommit階段
3PC的CanCommit階段其實(shí)和2PC的準(zhǔn)備階段很像。協(xié)調(diào)者向參與者發(fā)送commit請(qǐng)求,參與者如果可以提交就返回Yes響應(yīng),否則返回No響應(yīng)。
1.事務(wù)詢(xún)問(wèn) 協(xié)調(diào)者向參與者發(fā)送CanCommit請(qǐng)求。詢(xún)問(wèn)是否可以執(zhí)行事務(wù)提交操作。然后開(kāi)始等待參與者的響應(yīng)。
2.響應(yīng)反饋 參與者接到CanCommit請(qǐng)求之后,正常情況下,如果其自身認(rèn)為可以順利執(zhí)行事務(wù),則返回Yes響應(yīng),并進(jìn)入預(yù)備狀態(tài)。否則反饋No
PreCommit階段
協(xié)調(diào)者根據(jù)參與者的反應(yīng)情況來(lái)決定是否可以記性事務(wù)的PreCommit操作。根據(jù)響應(yīng)情況,有以下兩種可能。
假如協(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.響應(yīng)反饋 如果參與者成功的執(zhí)行了事務(wù)操作,則返回ACK響應(yīng),同時(shí)開(kāi)始等待最終指令。
假如有任何一個(gè)參與者向協(xié)調(diào)者發(fā)送了No響應(yīng),或者等待超時(shí)之后,協(xié)調(diào)者都沒(méi)有接到參與者的響應(yīng),那么就執(zhí)行事務(wù)的中斷。
1.發(fā)送中斷請(qǐng)求 協(xié)調(diào)者向所有參與者發(fā)送abort請(qǐng)求。
2.中斷事務(wù) 參與者收到來(lái)自協(xié)調(diào)者的abort請(qǐng)求之后(或超時(shí)之后,仍未收到協(xié)調(diào)者的請(qǐng)求),執(zhí)行事務(wù)的中斷。
doCommit階段
該階段進(jìn)行真正的事務(wù)提交,也可以分為以下兩種情況。
執(zhí)行提交
1.發(fā)送提交請(qǐng)求 協(xié)調(diào)接收到參與者發(fā)送的ACK響應(yīng),那么他將從預(yù)提交狀態(tài)進(jìn)入到提交狀態(tài)。并向所有參與者發(fā)送doCommit請(qǐng)求。
2.事務(wù)提交 參與者接收到doCommit請(qǐng)求之后,執(zhí)行正式的事務(wù)提交。并在完成事務(wù)提交之后釋放所有事務(wù)資源。
3.響應(yīng)反饋 事務(wù)提交完之后,向協(xié)調(diào)者發(fā)送Ack響應(yīng)。
4.完成事務(wù) 協(xié)調(diào)者接收到所有參與者的ack響應(yīng)之后,完成事務(wù)。
中斷事務(wù) 協(xié)調(diào)者沒(méi)有接收到參與者發(fā)送的ACK響應(yīng)(可能是接受者發(fā)送的不是ACK響應(yīng),也可能響應(yīng)超時(shí)),那么就會(huì)執(zhí)行中斷事務(wù)。
在doCommit階段,如果參與者無(wú)法及時(shí)接收到來(lái)自協(xié)調(diào)者的doCommit或者rebort請(qǐng)求時(shí),會(huì)在等待超時(shí)之后,會(huì)繼續(xù)進(jìn)行事務(wù)的提交。(其實(shí)這個(gè)應(yīng)該是基于概率來(lái)決定的,當(dāng)進(jìn)入第三階段時(shí),說(shuō)明參與者在第二階段已經(jīng)收到了PreCommit請(qǐng)求,那么協(xié)調(diào)者產(chǎn)生PreCommit請(qǐng)求的前提條件是他在第二階段開(kāi)始之前,收到所有參與者的CanCommit響應(yīng)都是Yes。(一旦參與者收到了PreCommit,意味他知道大家其實(shí)都同意修改了)所以,一句話概括就是,當(dāng)進(jìn)入第三階段時(shí),由于網(wǎng)絡(luò)超時(shí)等原因,雖然參與者沒(méi)有收到commit或者abort響應(yīng),但是他有理由相信:成功提交的幾率很大。 )
【責(zé)任編輯:武曉燕 TEL:(010)68476606】