經常使用的分佈式事務解決方案介紹有多少種?

關於分佈式事務,工程領域主要討論的是強一致性和最終一致性的解決方案。典型方案包括:git

  • 兩階段提交(2PC, Two-phase Commit)方案
  • eBay 事件隊列方案
  • TCC 補償模式
  • 緩存數據最終一致性

1、一致性理論

分佈式事務的目的是保障分庫數據一致性,而跨庫事務會遇到各類不可控制的問題,如個別節點永久性宕機,像單機事務同樣的ACID是沒法奢望的。另外,業界著名的CAP理論也告訴咱們,對分佈式系統,須要將數據一致性和系統可用性、分區容忍性放在天平上一塊兒考慮。github

兩階段提交協議(簡稱2PC)是實現分佈式事務較爲經典的方案,但2PC 的可擴展性不好,在分佈式架構下應用代價較大,eBay 架構師Dan Pritchett 提出了BASE 理論,用於解決大規模分佈式系統下的數據一致性問題。BASE 理論告訴咱們:能夠經過放棄系統在每一個時刻的強一致性來換取系統的可擴展性。算法

一、CAP理論

在分佈式系統中:數據庫

  • 一致性(Consistency)
  • 可用性(Availability)
  • 分區容忍性(Partition Tolerance)

3個要素最多隻能同時知足兩個,不可兼得。其中,分區容忍性又是不可或缺的。緩存

  • 一致性:分佈式環境下多個節點的數據是否強一致。
  • 可用性:分佈式服務能一直保證可用狀態。當用戶發出一個請求後,服務能在有限時間內返回結果。
  • 分區容忍性:特指對網絡分區的容忍性。

舉例:Cassandra、Dynamo 等,默認優先選擇AP,弱化C;HBase、MongoDB 等,默認優先選擇CP,弱化A。網絡

二、BASE 理論

核心思想:架構

  • 基本可用(BasicallyAvailable):指分佈式系統在出現故障時,容許損失部分的可用性來保證核心可用。
  • 軟狀態(SoftState):指容許分佈式系統存在中間狀態,該中間狀態不會影響到系統的總體可用性。
  • 最終一致性(EventualConsistency):指分佈式系統中的全部副本數據通過必定時間後,最終可以達到一致的狀態。

2、一致性模型

數據的一致性模型能夠分紅如下 3 類:app

  • 強一致性:數據更新成功後,任意時刻全部副本中的數據都是一致的,通常採用同步的方式實現
  • 弱一致性:數據更新成功後,系統不承諾當即能夠讀到最新寫入的值,也不承諾具體多久以後能夠讀到
  • 最終一致性:弱一致性的一種形式,數據更新成功後,系統不承諾當即能夠返回最新寫入的值,可是保證最終會返回上一次更新操做的值

分佈式系統數據的強一致性、弱一致性和最終一致性能夠經過Quorum NRW算法分析。框架

https://en.wikipedia.org/wiki/Quorum_(distributed_computing))異步

3、分佈式事務解決方案

一、2PC方案——強一致性

2PC的核心原理是經過提交分階段和記日誌的方式,記錄下事務提交所處的階段狀態,在組件宕機重啓後,可經過日誌恢復事務提交的階段狀態,並在這個狀態節點重試,如Coordinator重啓後,經過日誌能夠肯定提交處於Prepare仍是PrepareAll狀態,如果前者,說明有節點可能沒有Prepare成功,或全部節點Prepare成功但尚未下發Commit,狀態恢復後給全部節點下發RollBack;如果PrepareAll狀態,須要給全部節點下發Commit,數據庫節點須要保證Commit冪等。

2PC方案的問題:

  • 同步阻塞
  • 數據不一致
  • 單點問題

升級的3PC方案旨在解決這些問題,主要有兩個改進:

  • 增長超時機制
  • 兩階段之間插入準備階段

但三階段提交也存在一些缺陷,要完全從協議層面避免數據不一致,能夠採用Paxos或者Raft 算法。

Paxos:https://en.wikipedia.org/wiki/Paxos_(computer_science))

Raft:https://raft.github.io/

二、eBay 事件隊列方案——最終一致性

eBay 的架構師Dan Pritchett,曾在一篇解釋BASE 原理的論文《Base:An Acid Alternative》中提到一個eBay 分佈式系統一致性問題的解決方案。它的核心思想是將須要分佈式處理的任務經過消息或者日誌的方式來異步執行,消息或日誌能夠存到本地文件、數據庫或消息隊列,再經過業務規則進行失敗重試,它要求各服務的接口是冪等的。

Base:An Acid Alternative:https://link.zhihu.com/?target=http%3A//queue.acm.org/detail.cfm%3Fid%3D1394128

描述的場景爲,有用戶表user 和交易表transaction,用戶表存儲用戶信息、總銷售額和總購買額,交易表存儲每一筆交易的流水號、買家信息、賣家信息和交易金額。若是產生了一筆交易,須要在交易表增長記錄,同時還要修改用戶表的金額

論文中提出的解決方法是將更新交易表記錄和用戶表更新消息放在一個本地事務來完成,爲了不重複消費用戶表更新消息帶來的問題,增長一個操做記錄表updates_applied來記錄已經完成的交易相關的信息。

這個方案的核心在於第二階段的重試和冪等執行。失敗後重試,這是一種補償機制,它是能保證系統最終一致的關鍵流程。

三、TCC (Try-Confirm-Cancel)補償模式——最終一致性

某業務模型如圖,由服務 A、服務B、服務C、服務D 共同組成的一個微服務架構系統。服務A 須要依次調用服務B、服務C 和服務D 共同完成一個操做。當服務A 調用服務D 失敗時,若要保證整個系統數據的一致性,就要對服務B 和服務C 的invoke 操做進行回滾,執行反向的revert 操做。回滾成功後,整個微服務系統是數據一致的。

實現關鍵要素:

  • 服務調用鏈必須被記錄下來
  • 每一個服務提供者都須要提供一組業務邏輯相反的操做,互爲補償,同時回滾操做要保證冪等
  • 必須按失敗緣由執行不一樣的回滾策略

四、緩存數據最終一致性

在咱們的業務系統中,緩存(Redis 或者Memcached)一般被用在數據庫前面,做爲數據讀取的緩衝,使得I/O 操做不至於直接落在數據庫上。以商品詳情頁爲例,假如賣家修改了商品信息,並寫回到數據庫,可是這時候用戶從商品詳情頁看到的信息仍是從緩存中拿到的過期數據,這就出現了緩存系統和數據庫系統中的數據不一致的現象。

要解決該場景下緩存和數據庫數據不一致的問題咱們有如下兩種解決方案:

爲緩存數據設置過時時間。當緩存中數據過時後,業務系統會從數據庫中獲取數據,並將新值放入緩存。這個過時時間就是系統能夠達到最終一致的容忍時間。更新數據庫數據後同時清除緩存數據。數據庫數據更新後,同步刪除緩存中數據,使得下次對商品詳情的獲取直接從數據庫中獲取,並同步到緩存。

4、選擇建議

在面臨數據一致性問題的時候,首先要從業務需求的角度出發,肯定咱們對於3 種一致性模型的接受程度,再經過具體場景來決定解決方案。

從應用角度看,分佈式事務的現實場景經常沒法規避,在有能力給出其餘解決方案前,2PC也是一個不錯的選擇。

對購物轉帳等電商和金融業務,中間件層的2PC最大問題在於業務不可見,一旦出現不可抗力或意想不到的一致性破壞,如數據節點永久性宕機,業務難以根據2PC的日誌進行補償。金融場景下,數據一致性是命根,業務須要對數據有百分之百的掌控力,建議使用TCC這類分佈式事務模型,或基於消息隊列的柔性事務框架,這兩種方案都在業務層實現,業務開發者具備足夠掌控力,能夠結合SOA框架來架構,包括Dubbo、Spring Cloud等(題主的標籤寫了Dubbo)。

利益相關:

以上內容,基本都摘自網易雲基礎服務架構團隊著《雲原生應用架構實踐》

出處:網易雲
地址:https://www.zhihu.com/question/64921387

Contact

關注公衆號-搜雲庫

相關文章
相關標籤/搜索