分佈式事務 解決方案、原理

事務

1.1 什麼是事務mysql

數據庫事務(簡稱:事務,Transaction)是指數據庫執行過程當中的一個邏輯單位,由一個有限的數據庫操做序列構成。sql

事務擁有如下四個特性,習慣上被稱爲ACID特性:數據庫

  • 原子性(Atomicity):事務做爲一個總體被執行,包含在其中的對數據庫的操做要麼所有被執行,要麼都不執行。
  • 一致性(Consistency):事務應確保數據庫的狀態從一個一致狀態轉變爲另外一個一致狀態。一致狀態是指數據庫中的數據應知足完整性約束。除此以外,一致性還有另一層語義,就是事務的中間狀態不能被觀察到(這層語義也有說應該屬於原子性)。
  • 隔離性(Isolation):多個事務併發執行時,一個事務的執行不該影響其餘事務的執行,如同只有這一個操做在被數據庫所執行同樣。
  • 持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中。在事務結束時,此操做將不可逆轉。

1.2 本地事務編程

起初,事務僅限於對單一數據庫資源的訪問控制:架構


阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案


架構服務化之後,事務的概念延伸到了服務中。假若將一個單一的服務操做做爲一個事務,那麼整個服務操做只能涉及一個單一的數據庫資源:併發


阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案


這類基於單個服務單一數據庫資源訪問的事務,被稱爲本地事務(Local Transaction)。框架

分佈式事務

本地事務主要限制在單個會話內,不涉及多個數據庫資源。可是在基於SOA(Service-Oriented Architecture,面向服務架構)的分佈式應用環境下,愈來愈多的應用要求對多個數據庫資源,多個服務的訪問都能歸入到同一個事務當中,分佈式事務應運而生。nosql

最先的分佈式事務應用架構很簡單,不涉及服務間的訪問調用,僅僅是服務內操做涉及到對多個數據庫資源的訪問。分佈式


阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案


當一個服務操做訪問不一樣的數據庫資源,又但願對它們的訪問具備事務特性時,就須要採用分佈式事務來協調全部的事務參與者。高併發

對於上面介紹的分佈式事務應用架構,儘管一個服務操做會訪問多個數據庫資源,可是畢竟整個事務仍是控制在單一服務的內部。若是一個服務操做須要調用另一個服務,這時的事務就須要跨越多個服務了。在這種狀況下,起始於某個服務的事務在調用另一個服務的時候,須要以某種機制流轉到另一個服務,從而使被調用的服務訪問的資源也自動加入到該事務當中來。下圖反映了這樣一個跨越多個服務的分佈式事務:


阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案


若是將上面這兩種場景(一個服務能夠調用多個數據庫資源,也能夠調用其餘服務)結合在一塊兒,對此進行延伸,整個分佈式事務的參與者將會組成以下圖所示的樹形拓撲結構。在一個跨服務的分佈式事務中,事務的發起者和提交均系同一個,它能夠是整個調用的客戶端,也能夠是客戶端最早調用的那個服務。


阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案


較之基於單一數據庫資源訪問的本地事務,分佈式事務的應用架構更爲複雜。

在不一樣的分佈式應用架構下,實現一個分佈式事務要考慮的問題並不徹底同樣,好比對多資源的協調、事務的跨服務傳播等,實現機制也是複雜多變。儘管有這麼多工程細節須要考慮,但分佈式事務最核心的仍是其 ACID 特性。所以,想要了解一個分佈式事務,就先從瞭解它是怎麼實現事務 ACID 特性開始。

下文將從兩個最多見的分佈式事務模型入手,着重分析分佈式事務的基礎共通點,即如何保證分佈式事務的 ACID 特性。

常見的分佈式事務解決方案

1.基於XA協議的兩階段提交

XA是一個分佈式事務協議,由Tuxedo提出。XA中大體分爲兩部分:事務管理器和本地資源管理器。其中本地資源管理器每每由數據庫實現,好比Oracle、DB2這些商業數據庫都實現了XA接口,而事務管理器做爲全局的調度者,負責各個本地資源的提交和回滾。XA實現分佈式事務的原理以下:

阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案

總的來講,XA協議比較簡單,並且一旦商業數據庫實現了XA協議,使用分佈式事務的成本也比較低。可是,XA也有致命的缺點,那就是性能不理想,特別是在交易下單鏈路,每每併發量很高,XA沒法知足高併發場景。XA目前在商業數據庫支持的比較理想,在mysql數據庫中支持的不太理想,mysql的XA實現,沒有記錄prepare階段日誌,主備切換回致使主庫與備庫數據不一致。許多nosql也沒有支持XA,這讓XA的應用場景變得很是狹隘。

2.消息事務+最終一致性

所謂的消息事務就是基於消息中間件的兩階段提交,本質上是對消息中間件的一種特殊利用,它是將本地事務和發消息放在了一個分佈式事務裏,保證要麼本地操做成功成功而且對外發消息成功,要麼二者都失敗,開源的RocketMQ就支持這一特性,具體原理以下:

阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案

一、A系統向消息中間件發送一條預備消息

二、消息中間件保存預備消息並返回成功

三、A執行本地事務

四、A發送提交消息給消息中間件

經過以上4步完成了一個消息事務。對於以上的4個步驟,每一個步驟均可能產生錯誤,下面一一分析:

  • 步驟一出錯,則整個事務失敗,不會執行A的本地操做
  • 步驟二出錯,則整個事務失敗,不會執行A的本地操做
  • 步驟三出錯,這時候須要回滾預備消息,怎麼回滾?答案是A系統實現一個消息中間件的回調接口,消息中間件會去不斷執行回調接口,檢查A事務執行是否執行成功,若是失敗則回滾預備消息
  • 步驟四出錯,這時候A的本地事務是成功的,那麼消息中間件要回滾A嗎?答案是不須要,其實經過回調接口,消息中間件可以檢查到A執行成功了,這時候其實不須要A發提交消息了,消息中間件能夠本身對消息進行提交,從而完成整個消息事務

基於消息中間件的兩階段提交每每用在高併發場景下,將一個分佈式事務拆成一個消息事務(A系統的本地操做+發消息)+B系統的本地操做,其中B系統的操做由消息驅動,只要消息事務成功,那麼A操做必定成功,消息也必定發出來了,這時候B會收到消息去執行本地操做,若是本地操做失敗,消息會重投,直到B操做成功,這樣就變相地實現了A與B的分佈式事務。原理以下:

阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案

雖然上面的方案可以完成A和B的操做,可是A和B並非嚴格一致的,而是最終一致的,咱們在這裏犧牲了一致性,換來了性能的大幅度提高。固然,這種玩法也是有風險的,若是B一直執行不成功,那麼一致性會被破壞,具體要不要玩,仍是得看業務可以承擔多少風險。

3.TCC 模型

TCC(Try-Confirm-Cancel)分佈式事務模型相對於 XA 等傳統模型,其特徵在於它不依賴資源管理器(RM)對分佈式事務的支持,而是經過對業務邏輯的分解來實現分佈式事務。

TCC 模型認爲對於業務系統中一個特定的業務邏輯,其對外提供服務時,必須接受一些不肯定性,即對業務邏輯初步操做的調用僅是一個臨時性操做,調用它的主業務服務保留了後續的取消權。若是主業務服務認爲全局事務應該回滾,它會要求取消以前的臨時性操做,這就對應從業務服務的取消操做。而當主業務服務認爲全局事務應該提交時,它會放棄以前臨時性操做的取消權,這對應從業務服務的確認操做。每個初步操做,最終都會被確認或取消。

所以,針對一個具體的業務服務,TCC 分佈式事務模型須要業務系統提供三段業務邏輯:

初步操做 Try:完成全部業務檢查,預留必須的業務資源。

確認操做 Confirm:真正執行的業務邏輯,不做任何業務檢查,只使用 Try 階段預留的業務資源。所以,只要 Try 操做成功,Confirm 必須能成功。另外,Confirm 操做需知足冪等性,保證一筆分佈式事務有且只能成功一次。

取消操做 Cancel:釋放 Try 階段預留的業務資源。一樣的,Cancel 操做也須要知足冪等性。


阿里P8架構師談:分佈式事務的特徵、原理、以及常見3種解決方案


TCC 分佈式事務模型包括三部分:

1.主業務服務:主業務服務爲整個業務活動的發起方,服務的編排者,負責發起並完成整個業務活動。

2.從業務服務:從業務服務是整個業務活動的參與方,負責提供 TCC 業務操做,實現初步操做(Try)、確認操做(Confirm)、取消操做(Cancel)三個接口,供主業務服務調用。

3.業務活動管理器:業務活動管理器管理控制整個業務活動,包括記錄維護 TCC 全局事務的事務狀態和每一個從業務服務的子事務狀態,並在業務活動提交時調用全部從業務服務的 Confirm 操做,在業務活動取消時調用全部從業務服務的 Cancel 操做。

一個完整的 TCC 分佈式事務流程以下:

  1. 主業務服務首先開啓本地事務;
  2. 主業務服務向業務活動管理器申請啓動分佈式事務主業務活動;
  3. 而後針對要調用的從業務服務,主業務活動先向業務活動管理器註冊從業務活動,而後調用從業務服務的 Try 接口;
  4. 當全部從業務服務的 Try 接口調用成功,主業務服務提交本地事務;若調用失敗,主業務服務回滾本地事務;
  5. 若主業務服務提交本地事務,則 TCC 模型分別調用全部從業務服務的 Confirm 接口;若主業務服務回滾本地事務,則分別調用 Cancel 接口;
  6. 全部從業務服務的 Confirm 或 Cancel 操做完成後,全局事務結束。

TCC模型小結

所謂的TCC編程模式,也是兩階段提交的一個變種。TCC提供了一個編程框架,將整個業務邏輯分爲三塊:Try、Confirm和Cancel三個操做。以在線下單爲例,Try階段會去扣庫存,Confirm階段則是去更新訂單狀態,若是更新訂單失敗,則進入Cancel階段,會去恢復庫存。總之,TCC就是經過代碼人爲實現了兩階段提交,不一樣的業務場景所寫的代碼都不同,複雜度也不同,所以,這種模式並不能很好地被複用。

分佈式事務總結

分佈式事務,本質上是對多個數據庫的事務進行統一控制,按照控制力度能夠分爲:不控制、部分控制和徹底控制。不控制就是不引入分佈式事務,部分控制就是各類變種的兩階段提交,包括上面提到的消息事務+最終一致性、TCC模式,而徹底控制就是徹底實現兩階段提交。部分控制的好處是併發量和性能很好,缺點是數據一致性減弱了,徹底控制則是犧牲了性能,保障了一致性,具體用哪一種方式,最終仍是取決於業務場景。做爲技術人員,必定不能忘了技術是爲業務服務的,不要爲了技術而技術,針對不一樣業務進行技術選型也是一種很重要的能力!

相關文章
相關標籤/搜索