一、基礎(chǔ)理論
目前關(guān)于事務(wù)的幾大理論包括:ACID事務(wù)特性,CAP分布式理論,以及BASE等。ACID在數(shù)據(jù)庫事務(wù)中體現(xiàn),CAP和BASE則是分布式事務(wù)的理論,結(jié)合業(yè)務(wù)系統(tǒng),例如訂單管理,例如倉儲管理等,可以借鑒這些理論,從而解決問題。
1、ACID 特性
2、CAP特性
3、BASE特性
二、最終一致性的常用做法
1、單數(shù)據(jù)庫事務(wù)
如果應(yīng)用系統(tǒng)是單一的數(shù)據(jù)庫,那么這個(gè)很好保證,利用數(shù)據(jù)庫的事務(wù)特性來滿足事務(wù)的一致性,這時(shí)候的一致性是強(qiáng)一致性的。對于java應(yīng)用系統(tǒng)來講,很少直接通過事務(wù)的start和commit以及rollback來硬編碼,大多通過spring的事務(wù)模板或者聲明式事務(wù)來保證;
2、多數(shù)據(jù)庫事務(wù)
針對多數(shù)據(jù)庫事務(wù)可以根據(jù)二階段提交協(xié)議,采用spring 3.0 + Atomikos + JTA進(jìn)行支持;
3、基于事務(wù)型消息隊(duì)列的最終一致性
借助消息隊(duì)列,在處理業(yè)務(wù)邏輯的地方發(fā)送消息,業(yè)務(wù)邏輯處理成功后,提交消息,確保消息是發(fā)送成功的,之后消息隊(duì)列投遞來進(jìn)行處理,如果成功,則結(jié)束,如果沒有成功,則重試,直到成功,不過僅僅適用業(yè)務(wù)邏輯中,第一階段成功,第二階段必須成功的場景。對應(yīng)上圖中的C流程。
4、基于消息隊(duì)列+定時(shí)補(bǔ)償機(jī)制的最終一致性
前面部分和上面基于事務(wù)型消息的隊(duì)列,不同的是,第二階段重試的地方,不再是消息中間件自身的重試邏輯了,而是單獨(dú)的補(bǔ)償任務(wù)機(jī)制。其實(shí)在大多數(shù)的邏輯中,第二階段失敗的概率比較小,所以單獨(dú)獨(dú)立補(bǔ)償任務(wù)表出來,可以更加清晰,能夠比較明確的直到當(dāng)前多少任務(wù)是失敗的。對應(yīng)上圖的E流程。
5、異步回調(diào)機(jī)制的引入
A應(yīng)用調(diào)用B,在同步調(diào)用的返回結(jié)果中,B返回成功給到A,一般情況下,這時(shí)候就結(jié)束了,其實(shí)在99.99%的情況是沒問題的,但是有時(shí)候?yàn)榱舜_保100%,記住最起碼在系統(tǒng)設(shè)計(jì)中100%,這時(shí)候B系統(tǒng)再回調(diào)A一下,告訴A,你調(diào)用我的邏輯,確實(shí)成功了。其實(shí)這個(gè)邏輯,非常類似TCP協(xié)議中的三次握手。上圖中的B流程。
6、類似double check機(jī)制的確認(rèn)機(jī)制
還是上圖中異步回調(diào)的過程,A在同步調(diào)用B,B返回成功了。這次調(diào)用結(jié)束了,但是A為了確保,在過一段時(shí)間,這個(gè)時(shí)間可以是幾秒,也可以是每天定時(shí)處理,再調(diào)用B一次,查詢一下之前的那次調(diào)用是否成功。例如A調(diào)用B更新訂單狀態(tài),這時(shí)候成功了,延遲幾秒后,A查詢B,確認(rèn)一下狀態(tài)是否是自己剛剛期望的。上圖中的D流程。
三、分布式事務(wù)的缺點(diǎn)
1、二階段提交協(xié)議缺點(diǎn)
兩階段提交涉及到多個(gè)節(jié)點(diǎn)的網(wǎng)絡(luò)通信,通信時(shí)間如果過長,事務(wù)的相對時(shí)間也就會過長,那么鎖定資源的時(shí)間也就長了.在高并發(fā)的服務(wù)中,就會存在嚴(yán)重的性能瓶勁
2、消息隊(duì)列
在高并發(fā)的環(huán)境中,我們一般會采用消息隊(duì)列來避免分布式事務(wù)的執(zhí)行。
在使用消息隊(duì)列時(shí),我們需要做到可靠憑證的保存(分布式事務(wù)的消息),有如下幾種方式:
以支付寶和余額寶為例進(jìn)行說明.
支付寶完成扣錢的動作時(shí),記錄消息數(shù)據(jù),將消息數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù)存在同一個(gè)數(shù)據(jù)庫實(shí)例中.
Begin Transaction update A set amount=amount-1000 where uid=100; insert into message(uid,amount,status) values (1,1000,1)End TransactionCommit;
將支付寶完成扣錢的消息及時(shí)發(fā)送給余額寶,余額寶完成處理后返回成功消息,支付寶收到消息后,消除消息表中對應(yīng)的消息記錄,即完成本次扣錢操作.
傳統(tǒng)方式是,我做完了,發(fā)你消息。解決一致性的方案的意思就是,我先發(fā)你消息,我做完了再跟你確認(rèn)我做完了。這是改進(jìn)后的有事務(wù)的消息中間件。