我們專案本身分成了多套系統,但資料上有要求一致性的地方(比如訂單狀態,通俗點講就是系統a更新了訂單狀態為狀態一,那麼系統b也需要把相同訂單的訂單狀態更新成狀態一,這樣可以讓我們不管是讀系統a還是系統b的同乙個訂單的狀態,都可以讀出相同的狀態資料)。
最原始的偽**大概為:
sysa.db.transaction.commit();看了這個**後,大家應該知道這裡有個問題是呼叫系統b介面,可能出現網路或超時等問題,所以你是不知道系統b是執行成功了還是失敗,如果他是執行成功了的,那麼系統a回滾了就出問題了,因為兩邊資料就不一致了。
那麼基於cap理論的實現版base,我們採用資料最終一致方案。關於cap跟base,大家可以參考這裡
非同步任務處理,由原來同步呼叫b系統變為非同步呼叫。
系統a先寫資料庫更新訂單狀態,然後在本地同時新建乙個任務(任務初始狀態為待執行),當呼叫b系統介面完成之後該任務改為已經執行,修改訂單狀態跟建立任務需要在乙個資料庫事務下。
後台定時指令碼來執行待執行狀態的任務。
如果非同步呼叫系統b介面返回失敗,則需要對之前訂單狀態更新進行回退。
如果非同步呼叫系統b介面遇到網路問題或者超時,則考慮重試機制,注意重試機制要避免重複提交,可採取在系統a重試前確認和在系統b保證介面的冪等。
想了一下,這個方案有個問題就是狀態可能發生了多次改變,如果先後順序出現問題,那麼將造成訂單狀態更新錯誤,所以就得有個佇列來儲存訂單狀態的多次先後順序更新才行,於是有了方案二
引入訊息佇列,相當於對方案一的公升級版,新建立任務變成新建立訊息
系統a為訊息生產者,系統b為訊息消費者。
生產者系統a接收到使用者請求,先寫資料庫更新訂單狀態,然後寫一條更新訂單狀態的訊息到訊息佇列,並且要新建一張訊息狀態表用於記錄訊息的執行狀態(初始狀態為待執行),以上三個操作要在同乙個本地事務中進行,這個是容易忽略的地方。其實也可以在業務訂單表增加乙個字段用來表示訊息執行狀態。當然對於這個訂單的後續業務操作,只有在這個訊息執行成功後才能繼續,也就是有乙個因果先後關係在裡面才行。
消費者系統b取出一條訊息,進行相同訂單的狀態更新,處理完成後需要告訴系統a訊息執行結果,是成功還是失敗。這裡簡單說下失敗的情況,第一次失敗的話,系統b就可以進入重試邏輯,重試多次如果還是失敗才需要告訴系統a我這邊最終執行失敗了,你可能要採取點措施才行,比如回滾呀,還是什麼的。
分布式系統以基本可用跟快速高效的最終一致為目標
遠端rpc呼叫中的網路跟硬體等問題是造成一致性的主因,非同步解耦加訊息佇列等方式可作為分布式系統滿足最終一致性的乙個比較好的方案。
參考: 主要參考了此文,然後做了一些自己的理解跟修改
結合現有分布式系統的資料一致性思考
我們專案本身分成了多套系統,但資料上有要求一致性的地方 比如訂單狀態,通俗點講就是系統a更新了訂單狀態為狀態一,那麼系統b也需要把相同訂單的訂單狀態更新成狀態一,這樣可以讓我們不管是讀系統a還是系統b的同乙個訂單的狀態,都可以讀出相同的狀態資料 最原始的偽 大概為 sysa.db.transacti...
資料一致性,分布式系統
最近寫了乙個關於 鐵道部購票系統的若干文章 鐵道部新客票系統的設計 一 鐵道部新客票系統的設計 二 鐵道部新客票系統的設計 三 正好遇到乙個博友,諮詢了乙個問題,這個問題正好可以作為分布式系統的資料一致性的簡單例子,當然,這個只是比較簡單的情況 現在先丟擲問題,假設有乙個主資料中心在北京m,然後有成...
分布式系統資料一致性級別
在分布式系統中乙個需要解決的重要問題就是資料的複製。分布式系統對於資料的複製需求一般都來自於以下兩個原因 所謂的分布式一致性問題,是指在分布式環境中引入資料複製機制後,不同資料節點間可能出現的,並無法依靠計算機應用程式自身解決的資料不一致情況。簡單地講,資料一致性就是指在對乙個副本資料進行更新的同時...