問題的起源
分布式系統(tǒng)的特性
對分布式系統(tǒng)有過研究的讀者栅屏,可能聽說過“CAP定律”戈次、“Base理論”等馆里,非常巧的是隘世,化學理論中ACID是酸掉盅、Base恰好是堿。這里我們不對這些概念做過多的解釋以舒,有興趣的讀者可以查看相關參考資料趾痘。
這里針對一致性我們做個簡單的科普:
分布式事務有強一致,弱一致蔓钟,和最終一致性這三種:
強一致
當更新操作完成之后永票,任何多個后續(xù)進程或者線程的訪問都會返回最新的更新過的值。這種是對用戶最友好的滥沫,就是用戶上一次寫什么侣集,下一次就保證能讀到什么。根據(jù) CAP 理論兰绣,這種實現(xiàn)需要犧牲可用性世分。
弱一致
系統(tǒng)并不保證續(xù)進程或者線程的訪問都會返回最新的更新過的值。系統(tǒng)在數(shù)據(jù)寫入成功之后缀辩,不承諾立即可以讀到最新寫入的值臭埋,也不會具體的承諾多久之后可以讀到。
最終一致
弱一致性的特定形式臀玄。系統(tǒng)保證在沒有后續(xù)更新的前提下瓢阴,系統(tǒng)最終返回上一次更新操作的值。在沒有故障發(fā)生的前提下健无,不一致窗口的時間主要受通信延遲荣恐,系統(tǒng)負載和復制副本的個數(shù)影響。DNS 是一個典型的最終一致性系統(tǒng)
在分布式系統(tǒng)中累贤,同時滿足“CAP定律”中的“一致性”叠穆、“可用性”和“分區(qū)容錯性”三者是幾乎不可能的。在互聯(lián)網(wǎng)領域的絕大多數(shù)的場景臼膏,都需要犧牲強一致性來換取系統(tǒng)的高可用性硼被,系統(tǒng)往往只需要保證“最終一致性”,只要這個最終時間是在用戶可以接受的范圍內即可讶请,這時候我們只需要用短暫的數(shù)據(jù)不一致就可以達到我們想要效果祷嘶。
實例描述
比如有訂單,庫存兩個數(shù)據(jù)夺溢,一個下單過程簡化為论巍,加一個訂單,減一個庫存风响。 而訂單和庫存是獨立的服務嘉汰,那怎么保證數(shù)據(jù)一致性。
這時候我們需要思考一下状勤,怎么保證兩個遠程調用“同時成功”鞋怀,數(shù)據(jù)一致双泪?
請大家先注意一點遠程調用最郁悶的地方就是,結果有3種密似,成功焙矛、失敗和超時。 超時的話残腌,成功失敗都有可能村斟。
一般的解決方案,大多數(shù)的做法是借助mq來做最終一致抛猫。
如何實現(xiàn)最終一致
實例分析
我們是怎么利用Mq來達到最終一致的呢蟆盹?下面讓我們來一起進行詳細的分析:
訂單業(yè)務分析
首先,拿我們上面提到的訂單業(yè)務舉例:
- 在我們進行加訂單的過程中同時插入logA(這個過程是可以做本地事務的)
- 然后可以異步讀取logA闺金,發(fā)mqA
- B端接收mqA逾滥,同時減少庫存,B這里需要做冪等(避免因為重復消息造成的業(yè)務錯亂)
復雜的混合異步業(yè)務調用
那么我們通過上面的分析可能聯(lián)想到這樣的問題败匹?
本地先執(zhí)行事務寨昙,執(zhí)行成功了就發(fā)個消息過去,消費端拿到消息執(zhí)行自己的事務
比如a,b,c a異步調用b,c, 如果b失敗了哎壳,或者b成功毅待,或者b超時,那么怎么用mq讓他們最終一致呢归榕?b失敗就失敗了,b成功之后給c發(fā)一個消息吱涉,b和c對a來講都是異步的刹泄,且他們都是同時進行的話,而且需要a,b,c同時成功的情況怎爵,那么這種情況用mq怎么做
其實做法還是參照于本地事務的概念的特石。
- 第一種情況:假設a,b,c三者都正常執(zhí)行,那整個業(yè)務正常結束
- 第二種情況:假設b超時,那么需要a給b重發(fā)消息(記得b服務要做冪等)鳖链,如果出現(xiàn)重發(fā)失敗的話姆蘸,需要看情況,是終端服務芙委,還是繼續(xù)重發(fā)逞敷,甚至人為干預(所有的規(guī)則制定都需要根據(jù)業(yè)務規(guī)則來定)
- 第三種情況:假設a,b,c三者之中的一個失敗了,失敗的服務利用MQ給其他的服務發(fā)送消息,其他的服務接收消息,查詢本地事務記錄日志灌侣,如果本地也失敗推捐,刪除收到的消息(表示消息消費成功),如果本地成功的話侧啼,則需要調用補償接口進行補償(需要每個服務都提供業(yè)務補償接口)牛柒。
注意事項
mq這里有個坑堪簿,通常只適用于只允許第一個操作失敗的場景,也就是第一個成功之后必須保證后面的操作在業(yè)務上沒障礙皮壁,不然后面失敗了前面不好回滾椭更,只允許系統(tǒng)異常的失敗,不允許業(yè)務上的失敗蛾魄,通常業(yè)務上失敗一次后面基本上也不太可能成功了甜孤,要是因為網(wǎng)絡或宕機引起的失敗可以通過重試解決,如果業(yè)務異常畏腕,那就只能發(fā)消息給a和c讓他們做補償了吧缴川?通常是通過第三方進行補償,ABC提供補償接口描馅,設計范式里通常不允許消費下游業(yè)務失敗
上面的話我們該怎么理解呢把夸,舉個例子吧:
比如A給B轉賬,A先自己扣錢铭污,然后發(fā)了個消息恋日,B這邊如果在這之前銷戶了,那重試多少次也沒用嘹狞,只能人工干預
阿里在分布式事務采用的解決方式
阿里部分業(yè)務是用Mq實現(xiàn)了最終一致性岂膳,也有一部分業(yè)務用了tcc事務,但是tcc事務用的比較少磅网,因為會侵染業(yè)務谈截,開發(fā)成本比較高,如果體量不大的話直接用jta或mq支持事務就好涧偷,其實在分布式事務這一塊還有一種最大努力型簸喂,也比較無腦的一種方式。
聲明
以上觀點均為個人總結燎潮,不代表完全正確喻鳄。