其實分佈式事物也是個老大難的問題了,從提出到如今一直都沒有個特別優雅有效的解決方案,上週遇到個分佈式的問題,我想了好久,也查了不少資料。找了幾種方案,但都沒有達到本身的預期,如今先記錄下此時對分佈式事務的理解。數據庫
咱們能夠考慮下如下的場景,假設如今有一個電商平臺,包含的功能有訂單,支付,庫存。當咱們去電商平臺下一筆訂單,下單成功後電商平臺會跳轉到支付平臺,支付成功後會更新庫存的數據,而後電商平臺就能夠給咱們發貨了。api
假設在支付的時候,電商平臺向銀行發起扣款,可能銀行扣款成功了,可是給電商平臺返回結果的時候網絡出現了問題,沒能返回正確的支付結果信息。那電商平臺會認爲支付失敗,即不會給客戶發貨了。但實際上客戶的錢已經被扣了。緩存
針對這種狀況,咱們但願能把電商平臺和銀行這一整個支付流程放到一個事物裏面。服務器
這裏就產生了兩個問題:網絡
1.做爲電商平臺,銀行的代碼是不禁我控制的,我怎樣才能夠把它的代碼和個人代碼放到一個事物裏面呢?架構
2.目前的事務都是基於單數據庫的本地事務,目前的數據庫僅支持單庫事務,並不支持跨庫事務,如何能作到多數據的事務呢?異步
基於上述狀況,分佈式事務理論就出現了,着微服務架構的普及,一個大型業務系統每每由若干個子系統構成,這些子系統又擁有各自獨立的數據庫。每每一個業務流程須要由多個子系統共同完成,並且這些操做可能須要在一個事務中完成。在微服務系統中,這些業務場景是廣泛存在的。此時,咱們就須要在數據庫之上經過某種手段,實現支持跨數據庫的事務支持,這也就是你們常說的「分佈式事務」。分佈式
CAP理論說的是:在一個分佈式系統中,最多隻能知足C、A、P中的兩個需求。微服務
對於一個業務系統來講,可用性和分區容錯性是必需要知足的兩個條件,而且這二者是相輔相成的。業務系統之因此使用分佈式系統,主要緣由有兩個:post
提高總體性能 當業務量猛增,單個服務器已經沒法知足咱們的業務需求的時候,就須要使用分佈式系統,使用多個節點提供相同的功能,從而總體上提高系統的性能,這就是使用分佈式系統的第一個緣由。
實現分區容錯性 單一節點 或 多個節點處於相同的網絡環境下,那麼會存在必定的風險,萬一該機房斷電、該地區發生天然災害,那麼業務系統就全面癱瘓了。爲了防止這一問題,採用分佈式系統,將多個子系統分佈在不一樣的地域、不一樣的機房中,從而保證系統高可用性。
這說明分區容錯性是分佈式系統的根本,若是分區容錯性不能知足,那使用分佈式系統將失去意義。
此外,可用性對業務系統也尤其重要。在大談用戶體驗的今天,若是業務系統時常出現「系統異常」、響應時間過長等狀況,這使得用戶對系統的好感度大打折扣,在互聯網行業競爭激烈的今天,相同領域的競爭者不甚枚舉,系統的間歇性不可用會立馬致使用戶流向競爭對手。所以,咱們只能經過犧牲一致性來換取系統的可用性和分區容錯性。這也就是下面要介紹的BASE理論。
eBay的架構師Dan Pritchett源於對大規模分佈式系統的實踐總結,在ACM上發表文章提出BASE理論。文章連接:https://queue.acm.org/detail.cfm?id=1394128
BASE理論是對CAP理論的延伸,核心思想是即便沒法作到強一致性(Strong Consistency,CAP的一致性就是強一致性),但應用能夠採用適合的方式達到最終一致性(Eventual Consitency)。
BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫。
1. 基本可用(Basically Available):指分佈式系統在出現不可預知故障的時候,容許損失部分可用性。
2. 軟狀態( Soft State):指容許系統中的數據存在中間狀態,並認爲該中間狀態的存在不會影響系統的總體可用性。
3. 最終一致( Eventual Consistency):強調的是全部的數據更新操做,在通過一段時間的同步以後,最終都可以達到一個一致的狀態。所以,最終一致性的本質是須要系統保證最終數據可以達到一致,而不須要實時保證系統數據的強一致性。
服務模式是柔性事務流程中的特殊操做實現,如今大多數分佈式方案都會使用其中的幾個服務模式
服務操做具備全局惟一標識
可使用業務單據號(如訂單號)
或者使用系統分配的操做流水號(如支付記錄流水號)
或者使用操做資源的組合組合標識(如商戶號+商戶訂單號)
• 操做有惟一的、肯定的時間(約定以誰的時間爲準)
已支付爲例:提交一個支付請求後,可能同步返回和異步返回都會有問題,這個時候就須要咱們主動向支付渠道查詢支付結果
重複調用屢次產生的業務結果與調用一次產生的業務結果相同
Try: 嘗試執行業務
• 完成全部業務檢查(一致性)
• 預留必須業務資源(準隔離性)
Confirm:確認執行業務
• 真正執行業務
• 不做任何業務檢查
• 只使用Try階段預留的業務資源 • Confirm操做要知足冪等性
Cancel: 取消執行業務
• 釋放Try階段預留的業務資源 • Cancel操做要知足冪等性
1.抵銷(或部分抵銷)正向業務操做的業務結果
2.補償操做知足冪等性
業務活動的主動方在完成業務處理後,向業務活動被動方發送通知消息(容許消息丟失)
主動方能夠設置時間階梯型通知規則,在通知失敗後按規則重複通知,直到通知N次後再也不通知
主動方提供校對查詢接口給被動方按需校對查詢,用於恢復丟失的業務消息
這種方案在支付場景尤其常見,支付渠道通常會同時提供同步回調,異步回調,主動查詢,更精確的還會有對帳單的下載。
服務之間的通訊很難確保百分之百的成功,若是失敗了,在對於一致性要求不高的場合下,多試幾回總會成功的,這種思想對於分佈式事務的設計尤其重要。
消息中間件可以下降系統間的耦合性,在分佈式場景中,咱們也能夠經過消息幫助咱們實現分佈式事務。
這裏會有幾個問題:
1.業務執行成功後,確保消息必須可以發送
2.消費端必需要可以反饋消息的消費結果
針對上述兩個問題,咱們思考下可靠消息一致性的實現。
1.確保消息必須可以發送
1.1確保消息必須可以發送,咱們首先作的是先將將消息落地。因此咱們能夠將本地的業務操做和消息落地 放到一個本地事務中,若是消息落地失敗,業務也得回滾,這一步能夠保證一致性
1.2消息落地成功後,咱們能夠用一個定時器定時的根據消息的狀態,時間將消息投遞到mq的中間件------這一步有可能會出現異常(生成方投遞失敗)
2.消費端必需要可以反饋消息的消費結果
2.1消息若是投遞成功,消費端會消費消息,消費完成後,通知到消息生產方------這一步有可能會出現異常(通知生產者失敗)
這裏有兩種通知方式:
1.生產方提供服務接口給消費端調用
2.經過消息,消費端發送消費結果給生產端。
上述流程以下圖所示,咱們能夠將這種方式稱爲 本地消息服務
上述方案經過消息實現了分佈式事務,可是其中會有好幾個流程會致使事務的不一致,這裏咱們經過消息確認和消息查詢,消息生產者會定時根據消息狀態去投遞消息,因此若是消費者沒法正常的進行消息確認,那麼消息會不斷的進行投遞,因此消費端同時須要作冪等性。
雖然上述方案解決了一致性的要求,可是上面的系統耦合性過高了,主動方和被動方都存在互相調用的狀況,因此有了獨立消息服務的方案。
獨立消息服務指的是將消息的處理獨立出來,單獨造成一個服務,以下圖所示
具體的流程以下
1.主動方預發送消息到消息系統,消息系統保存消息,將保存結果反饋給主動方----可能直接發送失敗或者反饋的時候失敗
2.主動方收到正確的消息保存結果後,開始執行業務,業務執行完成後,將業務執行結果發送出去------可能存在發送失敗問題
3.消息服務收到業務執行結果後,對消息作更新或者刪除(對應業務的成功與失敗),而後投遞到中間件,消費端取消費------消費端可能獲取不到消息
4.消費端消費完成後,將消費結果返回-----可能沒法返回
上述各個流程都會出現異常,下面咱們來解決異常狀況
1.第一步若是出現異常,消息和業務都不會執行下去,數據的一致性獲得了保障,業務系統須要用定時任務保障這些未執行的業務
2.第二步若是出現異常了,業務執行了,可是消息未投遞出去,數據就不一致了,這時候須要消息服務定時的根據消息的時間和狀態查詢業務的狀態,以便能及時的更新消息狀態
3.第三步和第四步是同一個解決方案,對於消息系統來講,消息投遞出去後 若是消費端不給我ack,我是沒辦法知道我是否投遞成功的。因此對於長時間沒有ack的消息,消息系通通一都會認爲消息投遞失敗,再次進行投遞。這時候,消費端必需要作到冪等性。
相關代碼還在研究,待完成。。。
http://www.tianshouzhi.com/api/tutorials/distributed_transaction/383
https://juejin.im/post/5aa3c7736fb9a028bb189bca
http://www.roncoo.com/course/view/7ae3d7eddc4742f78b0548aa8bd9ccdb