结合现有分布式系统的数据一致性思考
背景
我們項(xiàng)目本身分成了多套系統(tǒng),但數(shù)據(jù)上有要求一致性的地方(比如訂單狀態(tài),通俗點(diǎn)講就是系統(tǒng)A更新了訂單狀態(tài)為狀態(tài)一,那么系統(tǒng)B也需要把相同訂單的訂單狀態(tài)更新成狀態(tài)一,這樣可以讓我們不管是讀系統(tǒng)A還是系統(tǒng)B的同一個訂單的狀態(tài),都可以讀出相同的狀態(tài)數(shù)據(jù))。
最原始的偽代碼大概為:
sysA.db.transaction.begin(); var success = sysA.db.transaction.updateOrderStatus(); if(!success){sysA.db.transaction.rollback();return; }success = httpclient.post(sysB.url); if(!success){sysA.db.transaction.rollback();return; }sysA.db.transaction.commit();看了這個代碼后,大家應(yīng)該知道這里有個問題是調(diào)用系統(tǒng)B接口,可能出現(xiàn)網(wǎng)絡(luò)或超時等問題,所以你是不知道系統(tǒng)B是執(zhí)行成功了還是失敗,如果他是執(zhí)行成功了的,那么系統(tǒng)A回滾了就出問題了,因?yàn)閮蛇厰?shù)據(jù)就不一致了。
那么基于CAP理論的實(shí)現(xiàn)版BASE,我們采用數(shù)據(jù)最終一致方案。關(guān)于CAP跟BASE,大家可以參考這里
然后我這里參考了個別文章跟同事想法,思考了其中兩個解決方案
簡單解決方案一
異步任務(wù)處理,由原來同步調(diào)用B系統(tǒng)變?yōu)楫惒秸{(diào)用。
系統(tǒng)A先寫數(shù)據(jù)庫更新訂單狀態(tài),然后在本地同時新建一個任務(wù)(任務(wù)初始狀態(tài)為待執(zhí)行),當(dāng)調(diào)用B系統(tǒng)接口完成之后該任務(wù)改為已經(jīng)執(zhí)行,修改訂單狀態(tài)跟建立任務(wù)需要在一個數(shù)據(jù)庫事務(wù)下。
后臺定時腳本來執(zhí)行待執(zhí)行狀態(tài)的任務(wù)。
如果異步調(diào)用系統(tǒng)B接口返回失敗,則需要對之前訂單狀態(tài)更新進(jìn)行回退。
如果異步調(diào)用系統(tǒng)B接口遇到網(wǎng)絡(luò)問題或者超時,則考慮重試機(jī)制,注意重試機(jī)制要避免重復(fù)提交,可采取在系統(tǒng)A重試前確認(rèn)和在系統(tǒng)B保證接口的冪等。
想了一下,這個方案有個問題就是狀態(tài)可能發(fā)生了多次改變,如果先后順序出現(xiàn)問題,那么將造成訂單狀態(tài)更新錯誤,所以就得有個隊(duì)列來保存訂單狀態(tài)的多次先后順序更新才行,于是有了方案二
簡單解決方案二
引入消息隊(duì)列,相當(dāng)于對方案一的升級版,新建立任務(wù)變成新建立消息
系統(tǒng)A為消息生產(chǎn)者,系統(tǒng)B為消息消費(fèi)者。
生產(chǎn)者系統(tǒng)A接收到用戶請求,先寫數(shù)據(jù)庫更新訂單狀態(tài),然后寫一條更新訂單狀態(tài)的消息到消息隊(duì)列,并且要新建一張消息狀態(tài)表用于記錄消息的執(zhí)行狀態(tài)(初始狀態(tài)為待執(zhí)行),以上三個操作要在同一個本地事務(wù)中進(jìn)行,這個是容易忽略的地方。其實(shí)也可以在業(yè)務(wù)訂單表增加一個字段用來表示消息執(zhí)行狀態(tài)。當(dāng)然對于這個訂單的后續(xù)業(yè)務(wù)操作,只有在這個消息執(zhí)行成功后才能繼續(xù),也就是有一個因果先后關(guān)系在里面才行。
消費(fèi)者系統(tǒng)B取出一條消息,進(jìn)行相同訂單的狀態(tài)更新,處理完成后需要告訴系統(tǒng)A消息執(zhí)行結(jié)果,是成功還是失敗。這里簡單說下失敗的情況,第一次失敗的話,系統(tǒng)B就可以進(jìn)入重試邏輯,重試多次如果還是失敗才需要告訴系統(tǒng)A我這邊最終執(zhí)行失敗了,你可能要采取點(diǎn)措施才行,比如回滾呀,還是什么的。
總結(jié)
分布式系統(tǒng)以基本可用跟快速高效的最終一致為目標(biāo)
遠(yuǎn)程RPC調(diào)用中的網(wǎng)絡(luò)跟硬件等問題是造成一致性的主因,異步解耦加消息隊(duì)列等方式可作為分布式系統(tǒng)滿足最終一致性的一個比較好的方案。
參考:
https://www.cnblogs.com/kerwing/p/9098893.html?主要參考了此文,然后做了一些自己的理解跟修改
https://www.cnblogs.com/frankltf/p/10374662.html
https://www.cnblogs.com/hzmark/p/consistency_model.html
聯(lián)系作者請?zhí)砑游⑿盘?#xff1a;sutong324,并注明:來自cnblogs
總結(jié)
以上是生活随笔為你收集整理的结合现有分布式系统的数据一致性思考的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: abp vnext2.0之核心组件模块加
- 下一篇: 《ASP.NET Core 微服务实战》
