【轉(zhuǎn)自】:http://www.cnblogs.com/duanxz/p/5226316.html
【參考】:http://www.roncoo.com/article/detail/124243
在當(dāng)前如火如荼的互聯(lián)網(wǎng)浪潮下,如何應(yīng)對海量數(shù)據(jù)、高并發(fā)成為大家面臨的普遍難題。廣大IT公司從以往的集中式網(wǎng)站架構(gòu),紛紛轉(zhuǎn)向分布式的網(wǎng)站架構(gòu),隨之而來的就是進行數(shù)據(jù)庫拆分和應(yīng)用拆分,如何在跨數(shù)據(jù)庫、跨應(yīng)用保證數(shù)據(jù)操作和業(yè)務(wù)操作的一致性、原子性,又成為需要解決的新的問題。從分布式事務(wù)的需求來源來看:
1、跨數(shù)據(jù)庫
數(shù)據(jù)庫拆分(水平、垂直)帶來的分布式事務(wù)->保證跨庫操作的原子性
基于單個JVM
2、跨應(yīng)用
應(yīng)用拆分帶來的分布式事務(wù)->保證跨應(yīng)用業(yè)務(wù)操作的原子性
跨JVM
跨應(yīng)用的業(yè)務(wù)操作原子性要求,其實是比較常見的。比如在第三方支付場景中的組合支付,用戶在電商網(wǎng)站購物后,要同時使用余額和紅包支付該筆訂單,而余額系統(tǒng)和紅包系統(tǒng)分別是不同的應(yīng)用系統(tǒng),支付系統(tǒng)在調(diào)用這兩個系統(tǒng)進行支付時,就需要保證余額扣減和紅包使用要么同時成功,要么同時失敗。
TCC事務(wù)的出現(xiàn)正是為了解決應(yīng)用拆分帶來的跨應(yīng)用業(yè)務(wù)操作原子性的問題。當(dāng)然,由于常規(guī)的XA事務(wù)(2PC,2 Phase Commit, 兩階段提交)性能上不盡如人意,也有通過TCC事務(wù)來解決數(shù)據(jù)庫拆分的使用場景(如賬務(wù)拆分),這個本文后續(xù)部分再詳述。
故從整個系統(tǒng)架構(gòu)的角度來看,分布式事務(wù)的不同方案是存在層次結(jié)構(gòu)的:
TCC的機制
明眼一看就知道,TCC應(yīng)該是三個英文單詞的首字母縮寫而來。沒錯,TCC分別對應(yīng)Try、Confirm和Cancel三種操作,這三種操作的業(yè)務(wù)含義如下:
Try:預(yù)留業(yè)務(wù)資源
Confirm:確認(rèn)執(zhí)行業(yè)務(wù)操作
Cancel:取消執(zhí)行業(yè)務(wù)操作
稍稍對照下關(guān)系型數(shù)據(jù)庫事務(wù)的三種操作:DML、Commit和Rollback,會發(fā)現(xiàn)和TCC有異曲同工之妙。在一個跨應(yīng)用的業(yè)務(wù)操作中,Try操作是先把多個應(yīng)用中的業(yè)務(wù)資源預(yù)留和鎖定住,為后續(xù)的確認(rèn)打下基礎(chǔ),類似的,DML操作要鎖定數(shù)據(jù)庫記錄行,持有數(shù)據(jù)庫資源;Confirm操作是在Try操作中涉及的所有應(yīng)用均成功之后進行確認(rèn),使用預(yù)留的業(yè)務(wù)資源,和Commit類似;而Cancel則是當(dāng)Try操作中涉及的所有應(yīng)用沒有全部成功,需要將已成功的應(yīng)用進行取消(即Rollback回滾)。其中Confirm和Cancel操作是一對反向業(yè)務(wù)操作。
簡而言之,TCC是應(yīng)用層的2PC(2 Phase Commit, 兩階段提交),如果你將應(yīng)用看做資源管理器的話。? ? ? ?詳細(xì)來說,TCC每項操作需要做的事情如下:
1、Try:嘗試執(zhí)行業(yè)務(wù)。
完成所有業(yè)務(wù)檢查(一致性)
預(yù)留必須業(yè)務(wù)資源(準(zhǔn)隔離性)
2、Confirm:確認(rèn)執(zhí)行業(yè)務(wù)。
真正執(zhí)行業(yè)務(wù)
不做任何業(yè)務(wù)檢查
只使用Try階段預(yù)留的業(yè)務(wù)資源
3、Cancel:取消執(zhí)行業(yè)務(wù)
釋放Try階段預(yù)留的業(yè)務(wù)資源
用一張圖來說明TCC的機制:
一個完整的TCC事務(wù)參與方包括三部分:
主業(yè)務(wù)服務(wù):主業(yè)務(wù)服務(wù)為整個業(yè)務(wù)活動的發(fā)起方,如前面提到的組合支付場景,支付系統(tǒng)即是主業(yè)務(wù)服務(wù)。
從業(yè)務(wù)服務(wù):從業(yè)務(wù)服務(wù)負(fù)責(zé)提供TCC業(yè)務(wù)操作,是整個業(yè)務(wù)活動的操作方。從業(yè)務(wù)服務(wù)必須實現(xiàn)Try、Confirm和Cancel三個接口,供主業(yè)務(wù)服務(wù)調(diào)用。由于Confirm和Cancel操作可能被重復(fù)調(diào)用,故要求Confirm和Cancel兩個接口必須是冪等的。前面的組合支付場景中的余額系統(tǒng)和紅包系統(tǒng)即為從業(yè)務(wù)服務(wù)。
業(yè)務(wù)活動管理器:業(yè)務(wù)活動管理器管理控制整個業(yè)務(wù)活動,包括記錄維護TCC全局事務(wù)的事務(wù)狀態(tài)和每個從業(yè)務(wù)服務(wù)的子事務(wù)狀態(tài),并在業(yè)務(wù)活動提交時確認(rèn)所有的TCC型操作的confirm操作,在業(yè)務(wù)活動取消時調(diào)用所有TCC型操作的cancel操作。
可見整個TCC事務(wù)對于主業(yè)務(wù)服務(wù)來說是透明的,其中業(yè)務(wù)活動管理器和從業(yè)務(wù)服務(wù)各自干了一部分工作。
TCC的優(yōu)點和限制
TCC事務(wù)的優(yōu)點如下:
解決了跨應(yīng)用業(yè)務(wù)操作的原子性問題,在諸如組合支付、賬務(wù)拆分場景非常實用。
TCC實際上把數(shù)據(jù)庫層的二階段提交上提到了應(yīng)用層來實現(xiàn),對于數(shù)據(jù)庫來說是一階段提交,規(guī)避了數(shù)據(jù)庫層的2PC性能低下問題。
TCC事務(wù)的缺點,主要就一個:
TCC的Try、Confirm和Cancel操作功能需業(yè)務(wù)提供,開發(fā)成本高。
當(dāng)然,對TCC事務(wù)的這個缺點是否是缺點,是一個見仁見智的事情。
一個案例理解
TCC說實話,TCC的理論有點讓人費解。故接下來將以賬務(wù)拆分為例,對TCC事務(wù)的流程做一個描述,希望對理解TCC有所幫助。? ? ? ?賬務(wù)拆分的業(yè)務(wù)場景如下,分別位于三個不同分庫的帳戶A、B、C,A和B一起向C轉(zhuǎn)帳共80元:
1、Try:嘗試執(zhí)行業(yè)務(wù)。
完成所有業(yè)務(wù)檢查(一致性):檢查A、B、C的帳戶狀態(tài)是否正常,帳戶A的余額是否不少于30元,帳戶B的余額是否不少于50元。
預(yù)留必須業(yè)務(wù)資源(準(zhǔn)隔離性):帳戶A的凍結(jié)金額增加30元,帳戶B的凍結(jié)金額增加50元,這樣就保證不會出現(xiàn)其他并發(fā)進程扣減了這兩個帳戶的余額而導(dǎo)致在后續(xù)的真正轉(zhuǎn)帳操作過程中,帳戶A和B的可用余額不夠的情況。
2、Confirm:確認(rèn)執(zhí)行業(yè)務(wù)。
真正執(zhí)行業(yè)務(wù):如果Try階段帳戶A、B、C狀態(tài)正常,且?guī)鬉、B余額夠用,則執(zhí)行帳戶A給賬戶C轉(zhuǎn)賬30元、帳戶B給賬戶C轉(zhuǎn)賬50元的轉(zhuǎn)帳操作。
不做任何業(yè)務(wù)檢查:這時已經(jīng)不需要做業(yè)務(wù)檢查,Try階段已經(jīng)完成了業(yè)務(wù)檢查。
只使用Try階段預(yù)留的業(yè)務(wù)資源:只需要使用Try階段帳戶A和帳戶B凍結(jié)的金額即可。
3、Cancel:取消執(zhí)行業(yè)務(wù)
釋放Try階段預(yù)留的業(yè)務(wù)資源:如果Try階段部分成功,比如帳戶A的余額夠用,且凍結(jié)相應(yīng)金額成功,帳戶B的余額不夠而凍結(jié)失敗,則需要對帳戶A做Cancel操作,將帳戶A被凍結(jié)的金額解凍掉。
小結(jié):到底要不要使用TCC到底要不要使用TCC事務(wù),取決于以下幾點:
是否真正有保證跨應(yīng)用業(yè)務(wù)操作的原子性需求。
研發(fā)上能否投入資源開發(fā)相對應(yīng)的TCC接口。
當(dāng)然還有最后一點,能否搞定一個穩(wěn)定的、高可用的、擴展性強的TCC事務(wù)管理器。
一個問題,如果TCC事務(wù)在Try階段所有參與方(從業(yè)務(wù)服務(wù))成功了,但是Confirm階段部分參與方(從業(yè)務(wù)服務(wù))成功,如何處理?