背景
用戶支付完成會(huì)將支付狀態(tài)及訂單狀態(tài)保存在訂單數(shù)據(jù)庫(kù)中,由訂單服務(wù)去維護(hù)訂單數(shù)據(jù)庫(kù)。由庫(kù)存服務(wù)去維護(hù)庫(kù)存數(shù)據(jù)庫(kù)的信息。下圖是系統(tǒng)結(jié)構(gòu)圖:
如何實(shí)現(xiàn)兩個(gè)分布式服務(wù)(訂單服務(wù)、庫(kù)存服務(wù))共同完成一件事即訂單支付成功自動(dòng)減庫(kù)存,這里的關(guān)鍵是如何保證兩個(gè)分布式服務(wù)的事務(wù)的一致性。
嘗試解決上邊的需求,在訂單服務(wù)中遠(yuǎn)程調(diào)用減庫(kù)存接口,偽代碼如下:
訂單支付結(jié)果通知方法{
? 更新支付表中支付狀態(tài)為“成功”。
? 遠(yuǎn)程調(diào)用減庫(kù)存接口減庫(kù)存。
}
上邊的邏輯說(shuō)明:
- 更新支付表狀態(tài)為本地?cái)?shù)據(jù)庫(kù)操作。
- 遠(yuǎn)程調(diào)用減庫(kù)存接口為網(wǎng)絡(luò)遠(yuǎn)程調(diào)用請(qǐng)求。
- 為保存事務(wù)上邊兩步操作由spring控制事務(wù),當(dāng)遇到Exception異常則回滾本地?cái)?shù)據(jù)庫(kù)操作。
問(wèn)題如下: - 如果更新支付表失敗則拋出異常,不再執(zhí)行遠(yuǎn)程調(diào)用,此設(shè)想沒(méi)有問(wèn)題。
- 如果更新支付表成功,網(wǎng)絡(luò)遠(yuǎn)程調(diào)用超時(shí)會(huì)拉長(zhǎng)本地?cái)?shù)據(jù)庫(kù)事務(wù)時(shí)間,影響數(shù)據(jù)庫(kù)性能。
- 如果更新支付表成功,遠(yuǎn)程調(diào)用減庫(kù)存成功(減庫(kù)存數(shù)據(jù)庫(kù)commit成功),最后更新支付表commit失敗,此時(shí)出現(xiàn)操作不一致。
上邊的問(wèn)題涉及到分布式事務(wù)控制。
什么是分布式事務(wù)
什么是分布式系統(tǒng):
部署在不同結(jié)點(diǎn)上的系統(tǒng)通過(guò)網(wǎng)絡(luò)交互來(lái)完成協(xié)同工作的系統(tǒng)。
比如:充值加積分的業(yè)務(wù),用戶在充值系統(tǒng)向自己的賬戶充錢,在積分系統(tǒng)中自己積分相應(yīng)的增加。充值系統(tǒng)和積分系統(tǒng)是兩個(gè)不同的系統(tǒng),一次充值加積分的業(yè)務(wù)就需要這兩個(gè)系統(tǒng)協(xié)同工作來(lái)完成。
什么是事務(wù):
事務(wù)是指由一組操作組成的一個(gè)工作單元,這個(gè)工作單元具有原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)。
-
原子性:執(zhí)行單元中的操作要么全部執(zhí)行成功,要么全部失敗。如果有一部分成功一部分失敗那么成功的操作要全部回滾到執(zhí)行前的狀態(tài)。
-
一致性:執(zhí)行一次事務(wù)會(huì)使用數(shù)據(jù)從一個(gè)正確的狀態(tài)轉(zhuǎn)換到另一個(gè)正確的狀態(tài),執(zhí)行前后數(shù)據(jù)都是完整的。
-
隔離性:在該事務(wù)執(zhí)行的過(guò)程中,任何數(shù)據(jù)的改變只存在于該事務(wù)之中,對(duì)外界沒(méi)有影響,事務(wù)與事務(wù)之間是完全的隔離的。只有事務(wù)提交后其它事務(wù)才可以查詢到最新的數(shù)據(jù)。
-
持久性:事務(wù)完成后對(duì)數(shù)據(jù)的改變會(huì)永久性的存儲(chǔ)起來(lái),即使發(fā)生斷電宕機(jī)數(shù)據(jù)依然在。
什么是本地事務(wù):
本地事務(wù)就是用關(guān)系數(shù)據(jù)庫(kù)來(lái)控制事務(wù),關(guān)系數(shù)據(jù)庫(kù)通常都具有ACID特性,傳統(tǒng)的單體應(yīng)用通常會(huì)將數(shù)據(jù)全部存儲(chǔ)在一個(gè)數(shù)據(jù)庫(kù)中,會(huì)借助關(guān)系數(shù)據(jù)庫(kù)來(lái)完成事務(wù)控制。
什么是分布式事務(wù):
在分布式系統(tǒng)中一次操作由多個(gè)系統(tǒng)協(xié)同完成,這種一次事務(wù)操作涉及多個(gè)系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同完成的過(guò)程稱為分布式事務(wù)。這里強(qiáng)調(diào)的是多個(gè)系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同完成一個(gè)事務(wù)的過(guò)程,并不強(qiáng)調(diào)多個(gè)系統(tǒng)訪問(wèn)了不同的數(shù)據(jù)庫(kù),即使多個(gè)系統(tǒng)訪問(wèn)的是同一個(gè)數(shù)據(jù)庫(kù)也是分布式事務(wù),如下圖:
另外一種分布式事務(wù)的表現(xiàn)是,一個(gè)應(yīng)用程序使用了多個(gè)數(shù)據(jù)源連接了不同的數(shù)據(jù)庫(kù),當(dāng)一次事務(wù)需要操作多個(gè)數(shù)據(jù)源,此時(shí)也屬于分布式事務(wù),當(dāng)系統(tǒng)作了數(shù)據(jù)庫(kù)拆分后會(huì)出現(xiàn)此種情況。
分布式事務(wù)有哪些應(yīng)用場(chǎng)景:
- 電商系統(tǒng)中的下單扣庫(kù)存
電商系統(tǒng)中,訂單系統(tǒng)和庫(kù)存系統(tǒng)是兩個(gè)系統(tǒng),一次下單的操作由兩個(gè)系統(tǒng)協(xié)同完成 - 金融系統(tǒng)中的銀行卡充值
在金融系統(tǒng)中通過(guò)銀行卡向平臺(tái)充值需要通過(guò)銀行系統(tǒng)和金融系統(tǒng)協(xié)同完成。 - 教育系統(tǒng)中下單選課業(yè)務(wù)
在線教育系統(tǒng)中,用戶購(gòu)買課程,下單支付成功后學(xué)生選課成功,此事務(wù)由訂單系統(tǒng)和選課系統(tǒng)協(xié)同完成。 - SNS系統(tǒng)的消息發(fā)送
在社交系統(tǒng)中發(fā)送站內(nèi)消息同時(shí)發(fā)送手機(jī)短信,一次消息發(fā)送由站內(nèi)消息系統(tǒng)和手機(jī)通信系統(tǒng)協(xié)同完成。
如何進(jìn)行分布式事務(wù)控制
CAP理論
CAP理論是分布式事務(wù)處理的理論基礎(chǔ):分布式系統(tǒng)在設(shè)計(jì)時(shí)只能在一致性(Consistency)、可用性(Availability)、分區(qū)容忍性(PartitionTolerance)中滿足兩種,無(wú)法兼顧三種。
- 一致性(Consistency):服務(wù)A、B、C三個(gè)結(jié)點(diǎn)都存儲(chǔ)了用戶數(shù)據(jù), 三個(gè)結(jié)點(diǎn)的數(shù)據(jù)需要保持同一時(shí)刻數(shù)據(jù)一致性。
- 可用性(Availability):服務(wù)A、B、C三個(gè)結(jié)點(diǎn),其中一個(gè)結(jié)點(diǎn)宕機(jī)不影響整個(gè)集群對(duì)外提供服務(wù),如果只有服務(wù)A結(jié)點(diǎn),當(dāng)服務(wù)A宕機(jī)整個(gè)系統(tǒng)將無(wú)法提供服務(wù),增加服務(wù)B、C是為了保證系統(tǒng)的可用性。
- 分區(qū)容忍性(Partition Tolerance):分區(qū)容忍性就是允許系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同工作,分區(qū)容忍性要解決由于網(wǎng)絡(luò)分區(qū)導(dǎo)致數(shù)據(jù)的不完整及無(wú)法訪問(wèn)等問(wèn)題。
分布式系統(tǒng)不可避免的出現(xiàn)了多個(gè)系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同工作的場(chǎng)景,結(jié)點(diǎn)之間難免會(huì)出現(xiàn)網(wǎng)絡(luò)中斷、網(wǎng)延延遲等現(xiàn)象,這種現(xiàn)象一旦出現(xiàn)就導(dǎo)致數(shù)據(jù)被分散在不同的結(jié)點(diǎn)上,這就是網(wǎng)絡(luò)分區(qū)。
分布式系統(tǒng)如何兼顧C(jī)AP?
在保證分區(qū)容忍性的前提下一致性和可用性無(wú)法兼顧,如果要提高系統(tǒng)的可用性就要增加多個(gè)結(jié)點(diǎn),如果要保證數(shù)據(jù)的一致性就要實(shí)現(xiàn)每個(gè)結(jié)點(diǎn)的數(shù)據(jù)一致,結(jié)點(diǎn)越多可用性越好,但是數(shù)據(jù)一致性越差。所以,在進(jìn)行分布式系統(tǒng)設(shè)計(jì)時(shí),同時(shí)滿足“一致性”、“可用性”和“分區(qū)容忍性”三者是幾乎不可能的。
CAP有哪些組合方式?
- CA:放棄分區(qū)容忍性,加強(qiáng)一致性和可用性,關(guān)系數(shù)據(jù)庫(kù)按照CA進(jìn)行設(shè)計(jì)。
- AP:放棄一致性,加強(qiáng)可用性和分區(qū)容忍性,追求最終一致性,很多NoSQL數(shù)據(jù)庫(kù)按照AP進(jìn)行設(shè)計(jì)。
說(shuō)明:這里放棄一致性是指放棄強(qiáng)一致性,強(qiáng)一致性就是寫入成功立刻要查詢出最新數(shù)據(jù)。追求最終一致性是指允許暫時(shí)的數(shù)據(jù)不一致,只要最終在用戶接受的時(shí)間內(nèi)數(shù)據(jù) 一致即可。 - CP:放棄可用性,加強(qiáng)一致性和分區(qū)容忍性,一些強(qiáng)一致性要求的系統(tǒng)按CP進(jìn)行設(shè)計(jì),比如跨行轉(zhuǎn)賬,一次轉(zhuǎn)賬請(qǐng)求要等待雙方銀行系統(tǒng)都完成整個(gè)事務(wù)才算完成。說(shuō)明:由于網(wǎng)絡(luò)問(wèn)題的存在CP系統(tǒng)可能會(huì)出現(xiàn)待等待超時(shí),如果沒(méi)有處理超時(shí)問(wèn)題則整理系統(tǒng)會(huì)出現(xiàn)阻塞。
BASE 理論
-
強(qiáng)一致性和最終一致性
CAP 理論告訴我們一個(gè)分布式系統(tǒng)最多只能同時(shí)滿足一致性(Consistency)、可用性(Availability)和分區(qū)容忍性(Partition tolerance)這三項(xiàng)中的兩項(xiàng),其中AP在實(shí)際應(yīng)用中較多,AP 即舍棄一致性,保證可用性和分區(qū)容忍性,但是在實(shí)際生產(chǎn)中很多場(chǎng)景都要實(shí)現(xiàn)一致性,比如主數(shù)據(jù)庫(kù)向從數(shù)據(jù)庫(kù)同步數(shù)據(jù),即使不要一致性,但是最終也要將數(shù)據(jù)同步成功來(lái)保證數(shù)據(jù)一致,這種一致性和 CAP 中的一致性不同,CAP 中的一致性要求 在任何時(shí)間查詢每個(gè)結(jié)點(diǎn)數(shù)據(jù)都必須一致,它強(qiáng)調(diào)的是強(qiáng)一致性,但是最終一致性是允許可以在一段時(shí)間內(nèi)每個(gè)結(jié)點(diǎn)的數(shù)據(jù)不一致,但是經(jīng)過(guò)一段時(shí)間每個(gè)結(jié)點(diǎn)的數(shù)據(jù)必須一致,它強(qiáng)調(diào)的是最終數(shù)據(jù)的一致性。 -
Base 理論介紹
BASE 是 Basically Available(基本可用)、Soft state(軟狀態(tài))和 Eventually consistent (最終一致性)三個(gè)短語(yǔ)的縮寫。
BASE 理論是對(duì) CAP 中 AP 的一個(gè)擴(kuò)展,通過(guò)犧牲強(qiáng)一致性來(lái)獲得可用性,當(dāng)出現(xiàn)故障允許部分不可用但要保證核心功能可用,允許數(shù)據(jù)在一段時(shí)間內(nèi)是不一致的,但最終達(dá)到一致?tīng)顟B(tài)。滿足BASE理論的事務(wù),我們稱之為“柔性事務(wù)”。 -
基本可用:分布式系統(tǒng)在出現(xiàn)故障時(shí),允許損失部分可用功能,保證核心功能可用。如電商網(wǎng)站交易付款出現(xiàn)問(wèn)題了,商品依然可以正常瀏覽。
-
軟狀態(tài):由于不要求強(qiáng)一致性,所以BASE允許系統(tǒng)中存在中間狀態(tài)(也叫軟狀態(tài)),這個(gè)狀態(tài)不影響系統(tǒng)可用性,如訂單的"支付中"、“數(shù)據(jù)同步中”等狀態(tài),待數(shù)據(jù)最終一致后狀態(tài)改為“成功”狀態(tài)。
-
最終一致:最終一致是指經(jīng)過(guò)一段時(shí)間后,所有節(jié)點(diǎn)數(shù)據(jù)都將會(huì)達(dá)到一致。如訂單的"支付中"狀態(tài),最終會(huì)變 為“支付成功”或者"支付失敗",使訂單狀態(tài)與實(shí)際交易結(jié)果達(dá)成一致,但需要一定時(shí)間的延遲、等待。
小結(jié)
?在分布式系統(tǒng)設(shè)計(jì)中AP的應(yīng)用較多,即保證分區(qū)容忍性和可用性,犧牲數(shù)據(jù)的強(qiáng)一致性(寫操作后立刻讀取到最新數(shù)據(jù)),保證數(shù)據(jù)最終一致性。比如:訂單退款,今日退款成功,明日賬戶到賬,只要在預(yù)定的用戶可以接受的時(shí)間內(nèi)退款事務(wù)走完即可。
分布式事務(wù)一致性解決方案
兩階段提交協(xié)議(2PC)
? 為解決分布式系統(tǒng)的數(shù)據(jù)一致性問(wèn)題出現(xiàn)了兩階段提交協(xié)議(2 Phase Commitment Protocol),兩階段提交由協(xié)調(diào)者和參與者組成,共經(jīng)過(guò)兩個(gè)階段和三個(gè)操作,部分關(guān)系數(shù)據(jù)庫(kù)如Oracle、MySQL支持兩階段提交協(xié)議,本節(jié)講解關(guān)系數(shù)據(jù)庫(kù)兩階段提交協(xié)議。
2PC協(xié)議流程圖
-
第一階段:準(zhǔn)備階段(prepare)
協(xié)調(diào)者通知參與者準(zhǔn)備提交訂單,參與者開(kāi)始投票。
參與者完成準(zhǔn)備工作向協(xié)調(diào)者回應(yīng)Yes|NO。 -
第二階段:提交(commit)/回滾(rollback)階段
協(xié)調(diào)者根據(jù)參與者的投票結(jié)果發(fā)起最終的提交指令。
如果有參與者沒(méi)有準(zhǔn)備好則發(fā)起回滾指令。
應(yīng)用實(shí)例
一個(gè)下單減庫(kù)存的例子:
- 應(yīng)用程序連接兩個(gè)數(shù)據(jù)源。
- 應(yīng)用程序通過(guò)事務(wù)協(xié)調(diào)器向兩個(gè)庫(kù)發(fā)起prepare,兩個(gè)數(shù)據(jù)庫(kù)收到消息分別執(zhí)行本地事務(wù)(記錄日志),但不提交,如果執(zhí)行成功則回復(fù)yes,否則回復(fù)no。
- 事務(wù)協(xié)調(diào)器收到回復(fù),只要有一方回復(fù)no則分別向參與者發(fā)起回滾事務(wù),參與者開(kāi)始回滾事務(wù)。
- 事務(wù)協(xié)調(diào)器收到回復(fù),全部回復(fù)yes,此時(shí)向參與者發(fā)起提交事務(wù)。如果參與者有一方提交事務(wù)失敗則由事務(wù)協(xié)調(diào)器發(fā)起回滾事務(wù)。
2PC的優(yōu)缺點(diǎn)
2PC的優(yōu)點(diǎn):實(shí)現(xiàn)強(qiáng)一致性,部分關(guān)系數(shù)據(jù)庫(kù)支持(Oracle、MySQL等)。
缺點(diǎn):整個(gè)事務(wù)的執(zhí)行需要由協(xié)調(diào)者在多個(gè)節(jié)點(diǎn)之間去協(xié)調(diào),增加了事務(wù)的執(zhí)行時(shí)間,性能低下。
解決方案有:springboot+Atomikos or Bitronix
3PC主要是解決協(xié)調(diào)者與參與者通信阻塞問(wèn)題而產(chǎn)生的,它比2PC傳遞的消息還要多,性能不高。
XA 方案
2PC的傳統(tǒng)方案是在數(shù)據(jù)庫(kù)層面實(shí)現(xiàn)的,如 Oracle、MySQL 都支持 2PC 協(xié)議,為了統(tǒng)一標(biāo)準(zhǔn)減少行業(yè)內(nèi)不必要的對(duì)接成本,需要制定標(biāo)準(zhǔn)化的處理模型及接口標(biāo)準(zhǔn),國(guó)際開(kāi)放標(biāo)準(zhǔn)組織 Open Group 定義了分布式事務(wù)處理模型DTP(Distributed Transaction Processing Reference Model)。
為了讓大家更明確 XA 方案的內(nèi)容,下面以新用戶注冊(cè)送積分為例來(lái)說(shuō)明:
執(zhí)行流程如下:
- 應(yīng)用程序(AP)持有用戶庫(kù)和積分庫(kù)兩個(gè)數(shù)據(jù)源。
- 應(yīng)用程序(AP)通過(guò) TM 通知用戶庫(kù) RM 新增用戶,同時(shí)通知積分庫(kù)RM為該用戶新增積分,RM 此時(shí)并未提交事務(wù),此時(shí)用戶和積分資源鎖定。
- TM 收到執(zhí)行回復(fù),只要有一方失敗則分別向其他 RM 發(fā)起回滾事務(wù),回滾完畢,資源鎖釋放。
- TM 收到執(zhí)行回復(fù),全部成功,此時(shí)向所有 RM 發(fā)起提交事務(wù),提交完畢,資源鎖釋放。
DTP 模型定義如下角色:
- AP(Application Program):即應(yīng)用程序,可以理解為使用 DTP 分布式事務(wù)的程序。
- RM(Resource Manager):即資源管理器,可以理解為事務(wù)的參與者,一般情況下是指一個(gè)數(shù)據(jù)庫(kù)實(shí)例,通過(guò)資源管理器對(duì)該數(shù)據(jù)庫(kù)進(jìn)行控制,資源管理器控制著分支事務(wù)。
- TM(Transaction Manager):事務(wù)管理器,負(fù)責(zé)協(xié)調(diào)和管理事務(wù),事務(wù)管理器控制著全局事務(wù),管理事務(wù)生命周期,并協(xié)調(diào)各個(gè) RM。全局事務(wù)是指分布式事務(wù)處理環(huán)境中,需要操作多個(gè)數(shù)據(jù)庫(kù)共同完成一個(gè)工作,這個(gè)工作即是一個(gè)全局事務(wù)。
- DTP 模型定義TM和RM之間通訊的接口規(guī)范叫 XA,簡(jiǎn)單理解為數(shù)據(jù)庫(kù)提供的 2PC 接口協(xié)議,基于數(shù)據(jù)庫(kù)的 XA 協(xié)議來(lái)實(shí)現(xiàn) 2PC 又稱為 XA 方案
以上三個(gè)角色之間的交互方式如下:
- TM 向 AP 提供 應(yīng)用程序編程接口,AP 通過(guò) TM 提交及回滾事務(wù)。
- TM 交易中間件通過(guò) XA 接口來(lái)通知 RM 數(shù)據(jù)庫(kù)事務(wù)的開(kāi)始、結(jié)束以及提交、回滾等。
小結(jié)
整個(gè) 2PC 的事務(wù)流程涉及到三個(gè)角色 AP、RM、TM。AP 指的是使用 2PC 分布式事務(wù)的應(yīng)用程序;RM 指的是資源管理器,它控制著分支事務(wù);TM 指的是事務(wù)管理器,它控制著整個(gè)全局事務(wù)。
(1)在準(zhǔn)備階段 RM 執(zhí)行實(shí)際的業(yè)務(wù)操作,但不提交事務(wù),資源鎖定
(2)在提交階段 TM 會(huì)接受 RM 在準(zhǔn)備階段的執(zhí)行回復(fù),只要有任一個(gè)RM執(zhí)行失敗,TM 會(huì)通知所有 RM 執(zhí)行回滾操作,否則,TM 將會(huì)通知所有 RM 提交該事務(wù)。提交階段結(jié)束資源鎖釋放。
XA方案的問(wèn)題
需要本地?cái)?shù)據(jù)庫(kù)支持XA協(xié)議。
資源鎖需要等到兩個(gè)階段結(jié)束才釋放,性能較差。
事務(wù)補(bǔ)償 TCC
TCC事務(wù)補(bǔ)償是基于2PC實(shí)現(xiàn)的業(yè)務(wù)層事務(wù)控制方案,它是Try、Confirm和Cancel三個(gè)單詞的首字母,
含義如下
- Try 檢查及預(yù)留業(yè)務(wù)資源完成提交事務(wù)前的檢查,并預(yù)留好資源。
- Confirm確定執(zhí)行業(yè)務(wù)操作對(duì)try階段預(yù)留的資源正式執(zhí)行。
- Cancel取消執(zhí)行業(yè)務(wù)操作對(duì)try階段預(yù)留的資源釋放。
應(yīng)用實(shí)例
下邊用一個(gè)下單減庫(kù)存的業(yè)務(wù)為例來(lái)說(shuō)明:
1、Try
- 下單業(yè)務(wù)由訂單服務(wù)和庫(kù)存服務(wù)協(xié)同完成,在try階段訂單服務(wù)和庫(kù)存服務(wù)完成檢查和預(yù)留資源。
- 訂單服務(wù)檢查當(dāng)前是否滿足提交訂單的條件(比如:當(dāng)前存在未完成訂單的不允許提交新訂單)。
- 庫(kù)存服務(wù)檢查當(dāng)前是否有充足的庫(kù)存,并鎖定資源。
2、Confirm
- 訂單服務(wù)和庫(kù)存服務(wù)成功完成Try后開(kāi)始正式執(zhí)行資源操作。
- 訂單服務(wù)向訂單寫一條訂單信息。
- 庫(kù)存服務(wù)減去庫(kù)存。
3、Cancel
- 如果訂單服務(wù)和庫(kù)存服務(wù)有一方出現(xiàn)失敗則全部取消操作。
- 訂單服務(wù)需要?jiǎng)h除新增的訂單信息。
- 庫(kù)存服務(wù)將減去的庫(kù)存再還原。
TCC優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn):最終保證數(shù)據(jù)的一致性,在業(yè)務(wù)層實(shí)現(xiàn)事務(wù)控制,靈活性好。
- 缺點(diǎn):開(kāi)發(fā)成本高,每個(gè)事務(wù)操作每個(gè)參與者都需要實(shí)現(xiàn)try/confirm/cancel三個(gè)接口。
注意:TCC的try/confirm/cancel接口都要實(shí)現(xiàn)冪等性,在為在try、confirm、cancel失敗后要不斷重試。
什么是冪等性? 冪等性是指同一個(gè)操作無(wú)論請(qǐng)求多少次,其結(jié)果都相同。
冪等操作實(shí)現(xiàn)方式有:
1、操作之前在業(yè)務(wù)方法進(jìn)行判斷如果執(zhí)行過(guò)了就不再執(zhí)行。
2、緩存所有請(qǐng)求和處理的結(jié)果,已經(jīng)處理的請(qǐng)求則直接返回結(jié)果。
3、在數(shù)據(jù)庫(kù)表中加一個(gè)狀態(tài)字段(未處理,已處理),數(shù)據(jù)操作時(shí)判斷未處理時(shí)再處理。
可靠消息隊(duì)列實(shí)現(xiàn)最終一致性
本方案是將分布式事務(wù)拆分成多個(gè)本地事務(wù)來(lái)完成,并且由消息隊(duì)列異步協(xié)調(diào)完成,如下圖:
下邊以下單減少庫(kù)存為例來(lái)說(shuō)明:
可以把MQ去掉不使用MQ
1、訂單服務(wù)和庫(kù)存服務(wù)完成檢查和預(yù)留資源。
2、訂單服務(wù)在本地事務(wù)中完成添加訂單表記錄和添加“減少庫(kù)存任務(wù)消息”。
3、由定時(shí)任務(wù)根據(jù)消息表的記錄發(fā)送給MQ通知庫(kù)存服務(wù)執(zhí)行減庫(kù)存操作。
4、庫(kù)存服務(wù)執(zhí)行減少庫(kù)存,并且記錄執(zhí)行消息狀態(tài)(為避免重復(fù)執(zhí)行消息,在執(zhí)行減庫(kù)存之前查詢是否執(zhí)行過(guò)此消息)。
5、庫(kù)存服務(wù)向MQ發(fā)送完成減少庫(kù)存的消息。
6、訂單服務(wù)接收到完成庫(kù)存減少的消息后刪除原來(lái)添加的“減少庫(kù)存任務(wù)消息”。
實(shí)現(xiàn)最終事務(wù)一致要求:預(yù)留資源成功理論上要求正式執(zhí)行成功,如果執(zhí)行失敗會(huì)進(jìn)行重試,要求業(yè)務(wù)執(zhí)行方法實(shí)現(xiàn)冪等。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn) :
由MQ按異步的方式協(xié)調(diào)完成事務(wù),性能較高。
不用實(shí)現(xiàn)try/confirm/cancel接口,開(kāi)發(fā)成本比TCC低。
缺點(diǎn):
此方式基于關(guān)系數(shù)據(jù)庫(kù)本地事務(wù)來(lái)實(shí)現(xiàn),會(huì)出現(xiàn)頻繁讀寫數(shù)據(jù)庫(kù)記錄,浪費(fèi)數(shù)據(jù)庫(kù)資源,另外對(duì)于高并發(fā)操作不是最佳方案。
分布式事務(wù)解決方案之最大努力通知
什么是最大努力通知
最大努力通知也是一種解決分布式事務(wù)的方案,下邊是一個(gè)是充值的例子:
交互流程:
- 賬戶系統(tǒng)調(diào)用充值系統(tǒng)接口
- 充值系統(tǒng)完成支付處理向賬戶發(fā)起充值結(jié)果通知,若通知失敗,則充值系統(tǒng)按策略進(jìn)行重復(fù)通知
- 賬戶系統(tǒng)接收到充值結(jié)果通知修改充值狀態(tài)
- 賬戶系統(tǒng)未接收到通知會(huì)主動(dòng)調(diào)用充值系統(tǒng)的接口查詢充值結(jié)果
通過(guò)上邊的例子我們總結(jié)最大努力通知方案的目標(biāo):發(fā)起通知方通過(guò)一定的機(jī)制最大努力將業(yè)務(wù)處理結(jié)果通知到接收方。
具體包括:
- 有一定的消息重復(fù)通知機(jī)制。因?yàn)榻邮胀ㄖ娇赡軟](méi)有接收到通知,此時(shí)要有一定的機(jī)制對(duì)消息重復(fù)通知
- 消息校對(duì)機(jī)制。如果盡最大努力也沒(méi)有通知到接收方,或者接收方消費(fèi)消息后要再次消費(fèi),此時(shí)可由接收方主動(dòng)向通知方查詢消息信息來(lái)滿足需求。
最大努力通知與可靠消息一致性有什么不同?
解決方案思想不同
可靠消息一致性,發(fā)起通知方需要保證將消息發(fā)出去,并且將消息發(fā)到接收通知方,消息的可靠性關(guān)鍵由發(fā)起通知方來(lái)保證。最大努力通知,發(fā)起通知方盡最大的努力將業(yè)務(wù)處理結(jié)果通知為接收通知方,但是可能消息接收不到,此時(shí)需要接收通知方主動(dòng)調(diào)用發(fā)起通知方的接口查詢業(yè)務(wù)處理結(jié)果,通知的可靠性關(guān)鍵在接收通知方。
兩者的業(yè)務(wù)應(yīng)用場(chǎng)景不同
可靠消息一致性關(guān)注的是交易過(guò)程的事務(wù)一致,以異步的方式完成交易。最大努力通知關(guān)注的是交易后的通知事務(wù),即將交易結(jié)果可靠的通知出去。
技術(shù)解決方向不同
可靠消息一致性要解決消息從發(fā)出到接收的一致性,即消息發(fā)出并且被接收到。最大努力通知無(wú)法保證消息從發(fā)出到接收的一致性,只提供消息接收的可靠性機(jī)制。可靠機(jī)制是,最大努力的將消息通知給接收方,當(dāng)消息無(wú)法被接收方接收時(shí),由接收方主動(dòng)查詢消息(業(yè)務(wù)處理結(jié)果)
解決方案
通過(guò)對(duì)最大努力通知的理解,采用 MQ 的 ack 機(jī)制就可以實(shí)現(xiàn)最大努力通知。
方案1:
本方案是利用 MQ 的 ack 機(jī)制由 MQ 向接收通知方發(fā)送通知,流程如下:
-
發(fā)起通知方將通知發(fā)給 MQ。使用普通消息機(jī)制將通知發(fā)給MQ。
注意:如果消息沒(méi)有發(fā)出去可由接收通知方主動(dòng)請(qǐng)求發(fā)起通知方查詢業(yè)務(wù)執(zhí)行結(jié)果。(后邊會(huì)講) -
接收通知方監(jiān)聽(tīng) MQ。
-
接收通知方接收消息,業(yè)務(wù)處理完成回應(yīng) ack。
-
接收通知方若沒(méi)有回應(yīng) ack 則 MQ 會(huì)重復(fù)通知。
MQ會(huì)按照間隔 1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知間隔,直到達(dá)到通知要求的時(shí)間窗口上限。 -
接收通知方可通過(guò)消息校對(duì)接口來(lái)校對(duì)消息的一致性。
方案 2:
交互流程如下: -
發(fā)起通知方將消息發(fā)給 MQ。
使用可靠消息一致方案中的事務(wù)消息保證本地事務(wù)和消息的原子性,最終將通知先發(fā)給 MQ。 -
通知程序監(jiān)聽(tīng) MQ,接收 MQ 的消息。
方案 1 中接收通知方直接監(jiān)聽(tīng) MQ,方案 2 中由通知程序監(jiān)聽(tīng) MQ。 -
通知程序若沒(méi)有回應(yīng) ack 則 MQ 會(huì)重復(fù)通知。
通知程序通過(guò)互聯(lián)網(wǎng)接口協(xié)議(如 http、webservice)調(diào)用接收通知方案接口,完成通知。
通知程序調(diào)用接收通知方案接口成功就表示通知成功,即消費(fèi) MQ 消息成功,MQ 將不再向通知程序投遞通知消息。 -
接收通知方可通過(guò)消息校對(duì)接口來(lái)校對(duì)消息的一致性。
方案1和方案2的不同點(diǎn):
- 方案 1 中接收通知方與 MQ 接口,即接收通知方案監(jiān)聽(tīng) MQ,此方案主要應(yīng)用與內(nèi)部應(yīng)用之間的通知。
- 方案 2 中由通知程序與 MQ 接口,通知程序監(jiān)聽(tīng) MQ,收到 MQ 的消息后由通知程序通過(guò)互聯(lián)網(wǎng)接口協(xié)議調(diào)用接收通知方。此方案主要應(yīng)用于外部應(yīng)用之間的通知,例如支付寶、微信的支付結(jié)果通知。
小結(jié)
最大努力通知方案是分布式事務(wù)中對(duì)一致性要求最低的一種,適用于一些最終一致性時(shí)間敏感度低的業(yè)務(wù);最大努力通知方案需要實(shí)現(xiàn)如下功能:
- 消息重復(fù)通知機(jī)制
- 消息校對(duì)機(jī)制
分布式事務(wù)對(duì)比分析
2PC 最大的詬病是一個(gè)阻塞協(xié)議。RM 在執(zhí)行分支事務(wù)后需要等待 TM 的決定,此時(shí)服務(wù)會(huì)阻塞并鎖定資源。由于其阻塞機(jī)制和最差時(shí)間復(fù)雜度高,因此,這種設(shè)計(jì)不能適應(yīng)隨著事務(wù)涉及的服務(wù)數(shù)量增加而擴(kuò)展的需要,很難用于并發(fā)較高以及子事務(wù)生命周期較長(zhǎng)(long-running transactions) 的分布式服務(wù)中。
如果拿TCC事務(wù)的處理流程與2PC兩階段提交做比較,2PC 通常都是在跨庫(kù)的 DB 層面,而 TCC 則在應(yīng)用層面的處理,需要通過(guò)業(yè)務(wù)邏輯來(lái)實(shí)現(xiàn)。這種分布式事務(wù)的實(shí)現(xiàn)方式的優(yōu)勢(shì)在于,可以讓應(yīng)用自己定義數(shù)據(jù)操作的粒度,使得降低鎖沖突、提高吞吐量成為可能。而不足之處則在于對(duì)應(yīng)用的侵入性非常強(qiáng),業(yè)務(wù)邏輯的每個(gè)分支都需要實(shí)現(xiàn) Try、Con?rm、Cancel 三個(gè)操作。此外,其實(shí)現(xiàn)難度也比較大,需要按照網(wǎng)絡(luò)狀態(tài)、系統(tǒng)故障等不同的失敗原因?qū)?現(xiàn)不同的回滾策略。典型的使用場(chǎng)景:滿減,登錄送優(yōu)惠券等。
可靠消息最終一致性事務(wù)適合執(zhí)行周期長(zhǎng)且實(shí)時(shí)性要求不高的場(chǎng)景。引入消息機(jī)制后,同步的事務(wù)操作變?yōu)榛谙?zhí)行的異步操作, 避免了分布式事務(wù)中的同步阻塞操作的影響,并實(shí)現(xiàn)了兩個(gè)服務(wù)的解耦。典型的使用場(chǎng)景:注冊(cè)送積分,登錄送優(yōu)惠券等。
最大努力通知是分布式事務(wù)中要求最低的一種,適用于一些最終一致性時(shí)間敏感度低的業(yè)務(wù);允許發(fā)起通知方處理業(yè)務(wù)失敗,在接收通知方收到通知后積極進(jìn)行失敗處理,無(wú)論發(fā)起通知方如何處理結(jié)果都會(huì)不影響到接收通知方的后續(xù)處理;發(fā)起通知方需提供查詢執(zhí)行情況接口,用于接收通知方校對(duì)結(jié)果。典型的使用場(chǎng)景:銀行通知、支付結(jié)果通知等。
2PC | TCC | 可靠消息 | 最大努力通知 | |
---|---|---|---|---|
一致性 | 強(qiáng)一致性 | 最終一致性 | 最終一致性 | 最終一致性 |
吞吐量 | 低 | 中 | 高 | 高 |
實(shí)現(xiàn)復(fù)雜度 | 易 | 難 | 中 | 易 |
總結(jié)
以上講了什么是分布式事務(wù)以及它的應(yīng)用場(chǎng)景、如何進(jìn)行分布式控制最后講了分布式事務(wù)一致性的四種種解決方案以及對(duì)比分析。
在條件允許的情況下,我們盡可能選擇本地事務(wù)單數(shù)據(jù)源,因?yàn)樗鼫p少了網(wǎng)絡(luò)交互帶來(lái)的性能損耗,且避免了數(shù)據(jù)弱一致性帶來(lái)的種種問(wèn)題。若某系統(tǒng)頻繁且不合理的使用分布式事務(wù),應(yīng)首先從整體設(shè)計(jì)角度觀察服務(wù)的拆分是否合理,是否高內(nèi)聚低耦合?是否粒度太?。糠植际绞聞?wù)一直是業(yè)界難題,因?yàn)榫W(wǎng)絡(luò)的不確定性,而且我們習(xí)慣于拿分布式事務(wù)與單機(jī)事務(wù) ACID 做對(duì)比。
無(wú)論是數(shù)據(jù)庫(kù)層的 XA、還是應(yīng)用層 TCC、可靠消息、最大努力通知等方案,都沒(méi)有完美解決分布式事務(wù)問(wèn)題,它們不過(guò)是各自在性能、一致性、可用性等方面做取舍,尋求某些場(chǎng)景偏好下的權(quán)衡。
分布式事務(wù)框架,在這些理論基礎(chǔ)上,都進(jìn)行了或多或少的修訂,也有不少創(chuàng)新。比如LCN框架(lock,confirm,notify),就抽象出了控制方和發(fā)起方的概念,感興趣的可以自行了解。
在互聯(lián)網(wǎng)公司中,由于高并發(fā)量的訴求,在實(shí)際應(yīng)用中,相對(duì)于強(qiáng)事務(wù),大家普遍選用軟事務(wù)進(jìn)行業(yè)務(wù)處理。使用最多的,就是TCC、SAGA、本地消息表等解決方案。SAGA應(yīng)對(duì)長(zhǎng)事務(wù)特別拿手,但隔離性稍差;TCC一直型好并發(fā)高,但需要較多編碼;本地消息表應(yīng)用場(chǎng)景有限,耦合業(yè)務(wù)不能復(fù)用。各種解決方案都有它的利弊,一定要結(jié)合使用場(chǎng)景進(jìn)行選擇。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-847902.html
在框架方面,阿里的seata(早些年叫fescar),已經(jīng)得到了廣泛應(yīng)用,XA、TCC、SAGA等模式都支持,如果你需要這方面的功能,可以集成嘗試一下??蓞⒖嘉覍懙奈恼拢篠pring Cloud Alibaba 實(shí)戰(zhàn) Seata文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-847902.html
到了這里,關(guān)于【分布式】java實(shí)現(xiàn)分布式事務(wù)的五種方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!