分佈式事務和分佈式hash

分佈式事務是什麼?


分佈式事務就是保證各個微服務之間數據一致,本質上就是保證不一樣數據庫的數據一致性。一致性狀態包含算法

  • 強一致性,任什麼時候刻,全部節點中數據都是同樣的
  • 弱一致性,數據更新後,只能訪問到部分節點數據或者是所有訪問不到
  • 最終一致性,不保證任什麼時候刻同樣,但隨着時間推移最終會達到一致性狀態

所以,存在以下幾種方案:數據庫

2PC ,二階段提交是一種儘可能強一致性設計,引入一個事務協調者來協調和管理各參與者的提交和回滾,包含準備和提交兩個階段,階段之間同步阻塞,準備階段協調者有超時機制。編程

大體流程:服務器

  • 準備階段 向各個參與者發送準備命令,能夠理解爲把除了提交事務以外的事情都作好。全部參與者都返回準備成功則下一階段提交事務,不然下一階段協調者就會向全部參與者發送回滾事務的請求,即分佈式事務執行失敗。
  • 提交階段 可能提交事務也可能回滾事務,而且存在回滾失敗或者提交失敗,失敗以後就會不斷重試。

存在問題:負載均衡

  • 單點故障。協調者是一個單點。解決辦法,經過選舉獲得新的協調者,各個組件都記錄log
  • 同步阻塞,效率低。①階段之間阻塞。②其中一個參與者佔用了共享資源就只能阻塞等待。
  • 不肯定性。提交階段協調者發送提交命令以後,只有一個參與者收到命令,可是兩個都掛了,新的協調者並不知道接下來是提交或者是回滾。
  • 數據不一致。極端條件下數據不一致。

場景:目前支付寶使用2PC兩階段提交思想實現了分佈式事務服務,它是一個分佈式事務框架,用來保障在大規模分佈式環境下事務的最終一致性。框架

3PC,爲了解決2PC的不肯定性,包含準備,預提交,提交三個階段。準備階段只是詢問參與者的狀態,其餘階段分別對應2PC。相比2PC,參與者也有超時機制(防止在2PC協調者提交階段準備發送命令的時候掛了,參與者一直阻塞等待的狀況),而且新增了一個階段使得故障恢復以後協調者的決策複雜度下降(解決2PC的不肯定性,在將要發生不肯定性時,新協調者發現有一個參與者處於預提交或者提交階段,那麼代表已經通過了全部參與者的確認了,因此此時執行的就是提交命令)異步

場景:沒有找到具體實現,偏理論。分佈式

2PC 和 3PC 都不能保證數據100%一致,所以通常都須要有定時掃描補償機制。函數

TCC,2PC 和 3PC 都是數據庫層面的,而 TCC 是業務層面的分佈式事務。TCC指的是Try - Confirm - Cancel微服務

  • try,即資源的預留和鎖定。
  • Confirm,指的是確認操做,其實就是真正的執行。
  • Cancel,指的時撤銷操做,能夠理解爲撤銷預留階段的動做。

其也存在一個事務管理者,用來記錄TCC全局事務狀態提交或者回滾。其流程和2PC差很少。但業務的侵入較大、業務耦合度高,須要將原來一個接口能夠實現的邏輯拆分爲三個接口。

場景:TCC 須要提供三個接口,提升了編程的複雜性,而且依賴於業務方來配合提供這樣的接口,推行難度大,因此通常不推薦使用這種方式。

本地消息表,利用各個系統本地事務來實現分佈式事務。系統中會定義一個存放本地消息的表,通常都是放在數據庫中。

大體流程:

  • 當A被其餘系統調用須要業務執行時,將業務的執行操做和將消息放入本地消息表中的操做放在同一個事務中。
  • A定時輪詢本地消息表往mq中生產消息,失敗則重試。
  • B消費mq中的消息,並處理業務邏輯,若是本地事務失敗則重試,若是是業務失敗則通知A進行回滾。

場景:跨行轉帳可經過該方案實現。在銀行一的用戶A向銀行二的用戶B轉帳

  • 銀行一:在一個本地事務中扣掉A的錢並將轉帳消息寫入本地消息表中,若是本地事務失敗則失敗,若是本地事務成功,系統定時輪詢消息表並往mq中生產轉帳消息,失敗則重試。
  • 銀行二:mq 消息會被銀行二消費並往 B 的帳戶增長轉帳金額,執行失敗會不斷重試。

消息事務,只有阿里的RocketMQ支持,實現了最終一致性。

大體流程:

  • A向mq發送準備消息,失敗則直接取消,成功則執行本地事務。
  • 本地事務執行成功,向mq發送確認消息,失敗則回滾消息。
  • B按期消費mq中的確認消息,執行本地事務並回送ack消息,若是本地事務執行失敗,會不斷嘗試,若是是業務失敗,會向A發起回滾請求。
  • mq會按期輪詢全部準備消息,調用A提供的反查事務狀態接口,若是該準備消息本地事務執行成功則重發確認消息,否者直接回滾。

場景:用戶註冊成功後發送郵件、電商系統給用戶發送優惠券等須要保證最終一致性的場景。

最大努力通知,是最簡單的一種柔性事務,適用於一些對最終一致性不敏感的業務,且被動方的處理結果,並不會影響主動方的處理結果。

大體流程:

  • A本地事務執行完成以後,向MQ生產消息。
  • 會存在一個服務消費MQ消息並調用系統B的接口。
  • 若是B執行成功則OK,不然會一直嘗試N次,超過則放棄。

場景:最多見的場景就是支付回調,支付服務收到第三方服務支付成功通知後,先更新本身庫中訂單支付狀態,而後同步通知訂單服務支付成功。若是這次同步通知失敗,會經過異步腳步不斷重試地調用訂單服務的接口。

分佈式Hash是什麼?


咱們從分佈式系統中負載均衡的問題來描述分佈式hash。

常見的負載均衡算法以下:

隨機訪問策略。隨機訪問,可能形成服務器負載壓力不均衡。

輪詢策略。請求均勻分配,可是浪費了性能高的服務器的資源。

權重輪詢策略。根據權重輪詢,權重須要靜態配置,沒法自動調節。

Hash取模策略。經過hash取模,伸縮性差,當新增或者下線服務器機器時候,用戶與服務器的映射關係會大量失效。

一致性哈希策略。簡單來講就是將整個哈希值(int範圍)空間組織成一個虛擬的hash圓環,將每一個服務器標識符跟int最大hash取模,獲得一些對應在hash環上的點。用戶在訪問的時候,根據用戶的標識符使用一樣的hash函數取模,獲得hash環上的一點,但這一點極可能沒有服務器映射在上面,因此會順時針行走,遇到的第一臺服務器就是應該處理該用戶請求的服務器。

優勢:

  • 能夠任意動態添加、刪除節點,每次添加、刪除一個節點僅影響hash環上相鄰的節點。

缺點:

  • 會存在數據傾斜問題,由於hash值範圍很大(int範圍),用戶請求量也很大(hash取模分佈相對均勻),而服務器數量相對不多(hash取模分佈很不均勻),就會形成數據傾斜問題。解決辦法就是設置虛擬服務器,每一個真實服務器映射不少個虛擬服務器,這樣服務器數據大幅增長,hash取模分佈相對均勻。
相關文章
相關標籤/搜索