分佈式一致性
分佈式事務一致性方案
1、什麼是分佈式事務
1.1 事務
數據庫事務(簡稱:事務,Transaction)是指數據庫執行過程中的一個邏輯單位,由一個有限的數據庫操作序列構成。眾所周知,事務擁有 ACID 四個特性,即:原子性( Atomicity ),一致性( Consistency ),隔離性( Isolation ),持久性(Durability)。
1.2 分佈式事務
區別於基於單個服務單一數據庫資源訪問的本地事務(Local Transaction),分佈式事務指事務的參與者、支持事務的服務器、資源服務器以及事務管理器分別位於不同的分佈式系統的不同節點之上,且屬於不同的應用,分佈式事務需要保證這些操作要麼全部成功,要麼全部失敗。本質上來説,分佈式事務就是為了保證不同數據庫的數據一致性。
1.3 分佈式事務應用架構
本地事務主要限制在單個會話內,不涉及多個數據庫資源。但是在基於 SOA(Service-Oriented Architecture,面向服務架構) 的分佈式應用環境下,越來越多的應用要求對多個數據庫資源、多個服務以及多個服務對應的數據庫資源的訪問都能納入到同一個事務當中,分佈式事務應運而生。
1.4 數據一致性的基礎理論
- 弱一致性 Weak:系統並不保證續進程或者線程的訪問都會返回最新的更新過的值。系統在數據寫入成功之後,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之後可以讀到。比如:某些 cache 系統,百度搜索引擎。
-
最終一致性 Eventually:弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。在沒有故障發生的前提下,不一致窗口的時間主要受通信延遲,系統負載和複製副本的個數影響。比如:DNS,電子郵件、Amazon S3,Google 搜索引擎這樣的系統。
-
強一致性 Strong:新的數據一旦寫入,任何多個後續進程或者線程的訪問都會返回最新的更新過的值。比如:文件系統,RDBMS,Azure Table 都是強一致性的。
1.5 CAP 定理
CAP 理論由加州大學伯克利分校的計算機教授 Eric Brewer 在 2000 年提出,其核心思想是任何基於網絡的數據共享系統最多隻能滿足數據一致性(Consistency)、可用性 (Availability)和網絡分區容忍(Partition Tolerance)三個特性中的兩個。
- C (一致性):對某個指定的客户端來説,讀操作能返回最新的寫操作。
對於數據分佈在不同節點上的數據來説,如果在某個節點更新了數據,那麼在其他節點如果都能讀取到這個最新的數據,那麼就稱為強一致,如果有某個節點沒有讀取到,那就是分佈式不一致。
- A (可用性):非故障的節點在合理的時間內返回合理的響應(不是錯誤和超時的響應)。可用性的兩個關鍵一個是合理的時間,一個是合理的響應。
合理的時間指的是請求不能無限被阻塞,應該在合理的時間給出返回。合理的響應指的是系統應該明確返回結果並且結果是正確的,這裏的正確指的是比如應該返回 50,而不是返回 40。
- P (分區容錯性):當出現網絡分區後,系統能夠繼續工作。打個比方,這裏集羣有多台機器,有台機器網絡出現了問題,但是這個集羣仍然可以正常工作。
對於 CA 來説,放棄了 P,那麼當發生分區現象時,為了保證一致性,這個時候必須拒絕請求,但是 A 又不允許,在分佈式系統中,網絡無法 100% 可靠,分區其實是一個必然現象,所以分佈式系統理論上不可能選擇 CA 架構,只能選擇 CP 或者 AP 架構。
對於 CP 來説,放棄可用性,追求一致性和分區容錯性,我們的 ZooKeeper 其實就是追求的強一致。
對於 AP 來説,放棄一致性(這裏説的一致性是強一致性),追求分區容錯性和可用性,這是很多分佈式系統設計時的選擇,後面的 BASE 也是根據 AP 來擴展。
因此大家按照 CAP 理論在對熱門的分佈式系統進行判定,譬如認為 HBase、MongoDB 等是一個 CP 系統,Cassandra、Dynamo 等是 AP 系統,其實並不嚴謹,理由是 CAP 理論是對分佈式系統中一個數據無法同時達到可用性和一致性的斷言,而一個系統中往往存在很多類型的數據,部分數據(比如金額類)是需要強 一致性的,而另外一部分數據(比如訪問量等)並不要求強一致性,所以拿 CAP 並不是來劃分系統的, 而是指引設計者在設計分佈式系統時需要區分各種數據的特點,並仔細考慮在小概率的網絡分區發生時究竟為該數據選擇可用性還是一致性。
1.6 BASE 理論
核心思想:
- 基本可用(Basically Available):指分佈式系統在出現故障時,允許損失部分的可用性來保證核心功能可用。
- 軟狀態(Soft State):指允許分佈式系統存在中間狀態(也叫軟狀態),該中間狀態不會影響到系統的整體可用性。
- 最終一致性(Eventual Consistency):經過一段時間後,所有的分佈式節點數據達到一致狀態。
BASE 理論通過犧牲強一致性來獲取最終一致性,當出現故障時允許部分不可用但要保證核心功能可用,允許數據在一段時間內不一致,但最終達到一致狀態,滿足 BASE 理論的事物,稱之為柔性事務。
二、分佈式事務一致性解決方案
2.1 兩階段提交(2PC)
2PC(Two Phase Commitment Protocol)是分佈式事務中最經典的事務類型之一
兩個角色
一個事務協調者(coordinator):負責協調多個參與者進行事務投票及提交或回滾 多個事務參與者(participants):即本地事務執行者
兩個階段步驟
階段一:提交事務請求(投票階段)
1 事務詢問:協調者向所有的參與者發送事務內容,詢問是否可以執行事務提交,等待迴應。
2 執行事務:各節點參與者執行本地事務,並記錄 Undo 和 Redo 日誌
3 參與者反饋事務:如果成功執行事務,向協調者反饋 Yes,否則 No
階段二:執行事務提交
-
如果階段一反饋都是 Yes,則:
1 協調者發起事務提交請求
2 參與者提交事務(commit)
3 反饋事務提交結果
4 完成事務
-
如果階段一有反饋 No,則:
1 協調者發送回滾請求
2 參與者事務回滾(rollback)
3 返回回滾事務結果
4 中斷事務
如果任一資源管理器在第一階段返回準備失敗,那麼事務管理器會要求所有資源管理器在第二階段執行回滾操作。通過事務管理器的兩階段協調,最終所有資源管理器要麼全部提交,要麼全部回滾,最終狀態都是一致的。
3PC
兩段提交最大的問題就是:第二階段時,參與者沒有收到協調者的 commit/rollback 的指令,參與者就會一直處於等待指令狀態,整個事務 block 住。即:協調者的可用性是個關鍵。
因些引出了升級版的三段提交 3PC,3PC 把 2PC 的第一個階段變成了兩段,其核心理念是:在詢問的時候並不鎖定資源,除非所有人都同意了,才開始鎖資源。但三階段提交也存在一些缺陷,即:如果參與者收到了 preCommit 消息後,出現了網絡分區,那麼參與者等待超時後,都會進行事務的提交,必然會出現事務不一致的問題。
優缺點
優點: 儘量保證了數據的強一致,適合對數據強一致要求很高的關鍵領域。
缺點: 由於是強一致性,資源需要在事務內部等待,性能影響較大,吞吐率不高,不適合高併發與高性能的業務場景;因此並不適合在微服務架構體系下使用
2.2 補償事務 TCC(Try-Confirm-Cancel)
TCC 將事務提交分為 Try - Confirm - Cancel 三個操作。是改進版的二階段提交,Try 為第一階段,Confirm - Cancel 為第二階段。
- Try:業務校驗,預留必須業務資源。
- Confirm:真正執行業務,不再做業務校驗;使用 Try 階段預留的業務資源;try 成功,confirm 必定成功,需滿足冪等性。
- Cancel:釋放 Try 階段預留的業務資源;需滿足冪等性。
其核心在於將業務分為兩個操作步驟完成。不依賴 RM 對分佈式事務的支持,而是通過對業務邏輯的分解來實現分佈式事務。
- 當所有 try 方法均執行成功時,對全局事物進行提交,即由事物管理器調用每個微服務的 confirm 方法;
- 當任意一個方法 try 失敗(資源不足、網絡異常、代碼異常等等),由事物管理器調用每個微服務的 cancle 方法對全局事務進行回滾;
- 按照 TCC 的協議,Confirm 和 Cancel 是隻返回成功,不會返回失敗。如果由於網絡問題,或者服務器臨時故障,那麼事務管理器會進行重試,最終成功。
優缺點
優點: 相對於 2PC 較為簡單,Try 操作可以靈活選擇業務資源的鎖定粒度
缺點:Canfirm 和 Cancel 的冪等性很難保證;
TCC 屬於應用層的一種補償方式,對業務侵入性比較大,耦合性高;
開發成本很高,適用場景十分有限。
2.3 本地消息表
本地消息表的核心思想是將分佈式事務拆分成本地事務進行處理,是 eBay 架構師 Dan Pritchett 提出的分佈式系統一致性問題的解決方案,也是業界使用最多的。
其流程圖如下:
基本思路就是:
消息生產方,需要在業務數據庫中額外創建一個消息表,並記錄消息發送狀態,業務數據與消息在同一事務中提交。事務提交後,消息會經過 MQ 發送給消費方,如果消息發送失敗,會進行重試發送。
消息消費方處理 MQ 發來的消息,如果本地事務處理成功,表明已經處理成功了,如果處理失敗,那麼就會重試執行。如果是業務上面的失敗,可以給生產方發送一個業務補償消息,通知生產方進行回滾等操作。
生產方和消費方定時掃描本地消息表,把還沒處理完成的消息或者失敗的消息再發送一遍。如果有靠譜的自動對賬補賬邏輯,這種方案還是非常實用的。
優缺點
優點: 一種非常經典最終一致性實現方案。實現邏輯簡單,開發成本⽐較低
缺點:與業務場景綁定,⾼耦合,不可公⽤;本地消息表與業務數據表在同⼀個庫,佔⽤業務系統資源,量⼤可能會影響
2.4 MQ(非事務消息)
通常使用非事務消息支持的 MQ 產品,我們很難將業務操作與對 MQ 的操作放在一個本地事務域中管理。以“轉賬”為例,始終沒有辦法保證在扣款完成後,對方賬户增加的 MQ 消息投遞一定能成功。
我們來分析下可能的情況:
-
正常的流程:本地操作成功,MQ 投遞消息也成功 ;
-
異常流程: 本地操作失敗,不會向 MQ 中投遞消息了;
本地操作成功,MQ 消息投遞時失敗,拋出了異常,本地操作回滾;
目前來看,這些情況都沒有一致性問題。
那麼:若本地操作成功,MQ 投遞消息也成功,但 MQ 消費方消費失敗的情況該如何處理?
- 消息不能失效或者丟失,需要保證消息與業務操作一致,
主流的 MQ 產品都具有持久化消息的功能。如果消費者宕機或者消費失敗,都可以執行重試機制的。
- 避免消息重複消費,即使重複消費也不能因此影響業務結果。
保證消費者接口冪等性;保存消費日誌或消費狀態表,便於判斷;
但有一種場景,消費方程序異常或因異常數據引起的程序異常,即使重試多次仍會失敗的場景,仍無法保證系統間的一致性,這種情況只能通過設置預警人工訂正等其他補償方式來解決。
優缺點
優點: 性能和吞吐量是優於使用關係型數據庫消息表的方案
如果 MQ 自身和業務都具有高可用性,理論上是可以滿足大部分的業務場景的
缺點:無法完全保證系統間的一致性
2.5 MQ 事務消息
目前一些主流的 MQ 比如 RabbitMQ 和 Kafka 都不支持事務消息,Apache RocketMQ 在 4.3.0 版中已經支持分佈式事務消息,採用了 2PC(兩階段提交)+ 補償機制(事務狀態回查)的思想來實現了提交事務消息,同時增加一個補償邏輯來處理二階段超時或者失敗的消息,如下圖所示。
2.5.1 事務消息流程
(1) 正常事務消息的發送及提交
- 生產者發送 half 消息(半消息 )到服務端;
-
服務端將消息持久化之後,給生產者響應消息寫入結果(ACK 響應);
-
生產者根據發送結果執行本地事務邏輯(如果寫入失敗,此時 half 消息對業務不可見,本地邏輯不執行);
-
生產者根據本地事務執行結果向 Broker 服務端提交二次確認(Commit 或是 Rollback),Broker 服務端收到 Commit 狀態則將半事務消息標記為可投遞,訂閲方最終將收到該消息;Broker 服務端收到 Rollback 狀態則刪除半事務消息,訂閲方將不會接收該消息;
(2) 事務消息的補償流程
- 在網絡閃斷或者是應用重啟的情況下,可能導致生產者發送的二次確認消息未能到達服務端,經過固定時間後,服務端將會對沒有 Commit/Rollback 的事務消息(pending 狀態的消息)進行“回查”;
-
生產者收到回查消息後,檢查回查消息對應的本地事務執行的最終結果;
-
生產者根據本地事務狀態,再次提交二次確認給服務端,然後服務端重新對半事務消息 Commit 或者 Rollback;
2.5.2 事務消息原理
設計思想:RocketMQ 事務消息最主要的特點是:
- 一階段發送的 Half 消息對用户是不可見的;
- 事務回查機制
那麼如何做到寫入消息但是對用户不可見呢?
RocketMQ 事務消息的做法是:如果消息是 half 消息,將備份原消息的主題與消息消費隊列,然後改變主題為 RMQ_SYS_TRANS_HALF_TOPIC。由於消費組未訂閲該主題,故消費端無法消費 half 類型的消息。
如何實現事務回查? Broker 會啟動一個消息回查的定時任務,定時從事務消息 queue 中讀取所有待反查的消息。針對每個需要反查的半消息,Broker 會給對應的 Producer 發一個要求執行事務狀態反查的 RPC 請求。然後根據 RPC 返回響應中的反查結果,來決定這個半消息是需要提交還是回滾,或者後續繼續來反查。最後,提交或者回滾事務,將半消息標記為已處理狀態。
優缺點
優點:
- 系統解耦:消息之間獨立存儲,系統之間消息完成事務
- 複雜度低,實現較為簡單
缺點:
- 一次消息需要發送兩次請求(half 消息+commit or rollback)
- 業務中需要實現消息狀態回查接口
- 目前主流 MQ 中只有 RocketMQ 支持事務消息
2.6 Seata
Seata 是一款開源的分佈式事務解決方案,致力於提供高性能和簡單易用的分佈式事務服務。Seata 將為用户提供了 AT、TCC、SAGA 和 XA 事務模式,為用户打造一站式的分佈式解決方案。
- AT 模式是無侵入的分佈式事務解決方案,用户只需關注自己的“業務 SQL”,用户的 “業務 SQL” 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作,適用於不希望對業務進行改造的場景,幾乎 0 學習成本。
- TCC 模式需要用户根據自己的業務場景實現 Try、Confirm 和 Cancel 三個操作。事務發起方在一階段執行 Try 方法,在二階段提交執行 Confirm 方法,二階段回滾執行 Cancel 方法。TCC 模式是高性能分佈式事務解決方案,適用於核心系統等對性能有很高要求的場景。
- Saga 模式是長事務解決方案,適用於業務流程長且需要保證事務最終一致性的業務系統,Saga 模式一階段就會提交本地事務,無鎖,長流程情況下可以保證性能,多用於渠道層、集成層業務系統。事務參與者可能是其它公司的服務或者是遺留系統的服務,無法進行改造和提供 TCC 要求的接口,也可以使用 Saga 模式。
- XA 模式是分佈式強一致性的解決方案,但性能低而使用較少。
在我們之前的文章中已詳細講過 Seata 相關內容,感興趣的朋友可以點擊查看:http://mp.weixin.qq.com/s/3dNSF1MErKKkamYEYJhylQ
小結
綜上所述,分佈式系統的事務一致性本身就是一個技術難題,其主要難點在於“網絡通信的不可靠”。以上介紹的所有方案均有其優缺點和各自適用的場景,目前也沒有一種很簡單很完美的方案能夠應對所有場景。只能通過“確認機制”、“重試機制”、“補償機制”等各方面來解決一些問題。在綜合考慮可用性、性能、實現複雜度等各方面的情況上,比較好的選擇是“異步確保最終一致性”,只是具體實現方式上有一些差異。
參考:
http://blog.csdn.net/weixin_48563689/article/details/109136478
http://www.cnblogs.com/peteremperor/p/13551408.html
推薦閲讀
招賢納士
政採雲技術團隊(Zero),一個富有激情、創造力和執行力的團隊,Base 在風景如畫的杭州。團隊現有300多名研發小夥伴,既有來自阿里、華為、網易的“老”兵,也有來自浙大、中科大、杭電等校的新人。團隊在日常業務開發之外,還分別在雲原生、區塊鏈、人工智能、低代碼平台、中間件、大數據、物料體系、工程平台、性能體驗、可視化等領域進行技術探索和實踐,推動並落地了一系列的內部技術產品,持續探索技術的新邊界。此外,團隊還紛紛投身社區建設,目前已經是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等眾多優秀開源社區的貢獻者。如果你想改變一直被事折騰,希望開始折騰事;如果你想改變一直被吿誡需要多些想法,卻無從破局;如果你想改變你有能力去做成那個結果,卻不需要你;如果你想改變你想做成的事需要一個團隊去支撐,但沒你帶人的位置;如果你想改變本來悟性不錯,但總是有那一層窗户紙的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望參與到隨着業務騰飛的過程,親手推動一個有着深入的業務理解、完善的技術體系、技術創造價值、影響力外溢的技術團隊的成長過程,我覺得我們該聊聊。任何時間,等着你寫點什麼,發給 [email protected]
微信公眾號
文章同步發佈,政採雲技術團隊公眾號,歡迎關注
- 分佈式一致性
- Lucene 查詢原理解析
- MySQL 意向鎖
- Unsafe 魔法類應用體現 (LockSupport)
- 一次線上報錯引起對MySQL間隙鎖的研究
- RocketMQ 延時方案分析與總結
- dapr實戰(三)
- 數據中台建設實踐(二)- 數據治理之數據質量
- 政採雲 Flutter 動態 iconfont 實踐探索
- 【初識】面向體系結構模式的編程
- 軟件測試工程師必備之軟技能:結構化思維
- Sentinel 滑動窗口限流實現解析
- 如何高效生成百萬數據
- 政採雲Flutter低成本屏幕適配方案探索
- MySQL 之 InnoDB 鎖系統源碼分析
- DS 2.0 時代 API 操作姿勢
- Redis系列之Bitmaps
- 在政採雲如何寫前端技術方案文檔
- ElasticSearch簡介之倒排索引
- 詳解 HTTP2.0 及 HTTPS 協議