分佈式事物理論與實踐

在平常討論技術方向的時候,常常聽夥伴拋出一些概念高可用性,一致性關鍵詞。可是未必每一個
人都能把這些概念說清楚。今天咱們就來聊聊分佈式事物那些事,分享一下咱們在項目中是如何使用的。
1、CAP理論web

1.什麼是CAP理論數據庫

2000年,Eric Brewer教授在PODC的研討會上提出了一個猜測。一致性、可用性和分區容錯性三者沒法在分佈式系統中被同時知足,而且最多隻能知足其中兩個!Brewer教授當時想象的分佈式場景是webservice,一組websevrice後臺運行着衆多的server,對service的讀寫會反應到後臺的server集羣。
圖片描述網絡

強一致性 (Consistency):系統在執行過某項操做後仍然處於一致的狀態。在分佈式系統中,更新操做執行成功後全部的用戶都應該讀取到最新的值,這樣的系統被認爲具備強一致性。
可用性 (Availability):每個操做老是可以在必定的時間內返回結果,超時和不能返回結果均不符合條件。
分區容錯性(Partition Tolerance):分區容錯性能夠理解爲系統在存在網絡分區的狀況下仍然能夠接受請求。這裏網絡分區是指因爲某種緣由網絡被分紅若干個孤立的區域,而區域之間互不相通。還有一些人將分區容錯性理解爲系統對節點動態加入和離開的處理能力,由於節點的加入和離開能夠認爲是集羣內部的網絡分區。架構

2.系統爲何不能同時知足CAP特性app

以下圖所示,在網絡中有兩個節點分別爲G1和G2,這兩個節點上存儲着同一數據的不一樣副本,如今數據是一致的,兩個副本的值都爲V0,A、B分別是運行在G一、G2上與數據交互的應用程序。異步

圖片描述

在正常狀況下,操做過程以下(以下圖所示):
(1) A將V0更新,數據值爲V1;
(2) G1發送消息m給G2,數據V0更新爲V1;
(3) B讀取到G2中的數據V1。分佈式

圖片描述

若是發生網絡分區故障,那麼在操做的步驟(2)將發生錯誤:G1發送的消息不能傳送到G2上。這樣數據就處於不一致的狀態,B讀取到的就不是最新的數據,以下圖所示。若是咱們採用一些技術如阻塞、加鎖、集中控制等來保證數據的一致,那麼必然會影響到系統的可用性和分區容錯性。因此同時知足三點,老是須要放棄一部分。spa

圖片描述

系統知足三個條件中不一樣的兩個條件會具備不一樣的特色
放棄P,保證AC:若是想避免分區容錯性問題的發生,一種作法是將全部的數據(與事務相關的)都放到一臺機器上。
放棄A,保證CP:一旦遇到分區容錯故障,那麼受到影響的服務須要等待數據最終一致性
放棄C,保證AP:這裏所說的放棄一致性,而保留數據的最終一致性。該方式也是解決分佈式事物的主流方式。日誌

2、分佈式事物解決方案code

eBay的架構師Dan Pritchett 在2008年發給ACM的文檔。文章中描述了一個最多見的場景,若是產生了一筆交易,須要在交易表增長記錄,同時還要修改用戶表的金額。這兩個表屬於不一樣的遠程服務,涉及到分佈式事務一致性的問題。經典的解決方法,引入本地消息表和消息中間件,將寫入本地消息表、更新用戶表,發送Q放在一個本地事務中完成。同時爲了不重複消費用戶表消息帶來的問題,保證冪等性增長一個接收端記錄表。
舉個例子,系統中有如下兩個表user,transaction.

圖片描述

其中user表記錄用戶交易彙總信息,transaction表記錄每一個交易的詳細信息。transaction表和user表存儲在不一樣的節點上,那麼上述事務是一個分佈式事務。要消除這一分佈式事務,將它拆分紅兩個子事務。保證消息的冪等性還須要在接收端建立消息接收表message_applied(msg_id),保證不能重複接收消息。

begin transaction
  insert into transaction(xid, $seller_id, $buyer_id, $amount);
  put_to_queue "update user("seller",$seller_id,amount)";
  put_to_queue "update user("buyer",$buyer_id,amount)";
end transaction
--------------------------------------------------------
for each message in queue
  peek message
  begin transaction
    select count(*) as cnt from message_applied where msg_id=message.id
        and balance = message.balance and user_id=message.user_id
    if cnt == 0 
then
          if message.type = 「seller」 then
    update user SET amt_sold = amt_sold + message.amount where id = message.user_id;
else
update user set amt_bought = amt_bought + message.amount where id = message.user_id;
         insert into message_applied values(message.id); 
end
end transaction
end fors

第一階段:transation表和操做隊列在同一實例上,能夠經過本地的數據庫的事務保證。
第二階段:message_applied表和user表在同一個實上,能夠經過本地的數據的事務保證,當有重試或者重複消息過來時,經過message_applied表能夠判斷是不是重複數據。

3、實際項目對理論的實踐

  1. A、B兩個系統服務進行異步數據通訊
    本場景咱們採用Q做爲消息中間件。能夠借鑑ebay模式。

①應用A的業務邏輯、寫本地消息表、寫消息隊列放在一個隊列裏。寫消息隊列業務邏輯放在最後。
②全部步驟執行成功,事物提交。
③有一步驟執行失敗,則進行回滾。
④此方案須要在記錄服務A發送的完整消息日誌,以防Q出現問題進行消息補發,在B端建立接收表,去重,保證消息的冪等性。

  1. D調用A、B、C三個服務

本場景保證事物一致性有兩種解決方案,一種是調用中間服務出錯後回滾掉其餘全部服務的數據,這須要每一個應用提供回滾服務。另外一種認爲服務必定會調用成功,一旦出現問題,會不斷重試。下面會根據這兩種狀況進行詳細說明。
第一, 服務調用採用回滾方式處理,以下示意圖所示

圖片描述

以上思路仍是借鑑ebay模型來解決最終一致性問題。第二,不斷重試保證消息一致性相對第一種狀況要簡單一些。一旦調用異常須要記錄到錯誤表中不斷的進行重試。

相關文章
相關標籤/搜索