分佈式事務(一)原理概覽

系列目錄

分佈式事務(一)原理概覽html

分佈式事務(二)JTA規範java

分佈式事務(三)mysql對XA協議的支持node

分佈式事務(四)簡單樣例mysql

分佈式事務(五)源碼詳解算法

分佈式事務(六)總結提升spring

1、引子

事務(數據庫事務)是java開發工程師必須掌握的一項技能。又可分爲本地事務和分佈式事務,其中分佈式事務是進階爲高級開發工程師必會的技能。本文從概念、原理、實踐多角度剖析分佈式事務,但願有所收穫。sql

2、概念

2.1.本地事務

大部分狀況下,一個服務操做一個數據庫,這就是本地事務,ACID特性由數據庫提供支持,好比mysql innodb引擎。以下圖所示(網上的圖,挺好直接用):數據庫

spring 提供了2種方式實現:編程

  • 編程式:基於transactionTemplate去實現,適合手動精準控制事務的場景,少用。
  • 聲明式事務註解:@Transactional加在serviceImpl的方法上便可,這也是經常使用的方法。

關於本地事務這裏很少說,飛機票:本地事務飛機票。api

2.2.分佈式事務

當遇到複雜業務調用時,可能會出現跨庫多資源調用(一個事務管理器,多個資源)/多服務調用(多個事務管理器,多個資源),指望所有成功或失敗回滾,這就是分佈式事務,用以保證「操做多個隔離資源的數據一致性」。

2.3 相關協議發展歷史

3、DTP模型 & XA規範

背景

Mysql官方對於XA事務,描述以下:

  1. Mysql InnoDB引擎支持分佈式事務,mysql的XA實現是基於X/Open CAE 文檔中的 Distributed Transaction Processing: The XA Specification. (DTP XA規範)的。飛機票:13.3.7 XA Transactions官方飛機票。X/Open CAE解釋以下:
  • X/Open: X/Open是一個獨立的、全球性的開放系統組織,由世界上最大的信息系統供應商、用戶組織和軟件公司支持。其使命是經過開放系統的實際實施,爲用戶帶來更大的計算價值。
  • X/Open CAE規範: 即X/Open Common Applications Environment,這個環境覆蓋了高於硬件級別的,支持開放系統所需的一組標準。它提供了應用程序的可移植性和互操做性。
  1. MySQL Connector 5.0.0及更高版本直接支持XA,經過一個類接口爲您處理XA SQL語句接口。XA支持分佈式事務,即容許多個單獨的事務資源參與全局事務。事務資源一般是rdbms,但也多是其餘類型的資源。
  2. X/Open CAE文檔是發佈在open group官網上的,http://www.opengroup.org/public/pubs/catalog/c193.htm

在open group官網可查到,有2個XA規範,一個是XA,一個是XA+, 其中XA+是XA的超集,新定義了通訊資源管理器CRM的協議,建議直接看XA+便可。後續分析直接以XA+ 1994版爲準。官方下載連接以下:

看名字咱們就知道 XA規範是依託於DTP場景的,下面咱們分別從DTP模型、XA規範2個視角來剖析原理

3.1 DTP模型

依據X/Open《Distributed Transaction Processing: Reference Model, Version 3》上的介紹,DTP模型是一種軟件體系結構,它容許多個應用程序共享多個資源管理器提供的資源,並容許將它們的工做協調到全局事務中。

3.1.1 模型元素

要深度瞭解DTP,先看看模型內的元素概念,以下:

  • 應用程序(Application Program ,簡稱AP):每一個AP指定一個包含資源(如數據庫)的操做序列。AP定義全局事務的開始和結束,訪問事務邊界內的資源,一般決定是提交仍是回滾每一個事務。
  • 資源管理器(Resource Manager,簡稱RM):如數據庫、文件系統等,並提供訪問資源的方式。
  • 事務管理器(Transaction Manager ,簡稱TM):管理全局事務,負責分配事務惟一標識XID,監控事務的執行進度,並負責事務的提交、回滾等。若是RM是一個通訊資源管理器(CRM),那麼在執行兩個APs之間的通訊時,它將xid傳遞給合做夥伴、從屬的CRMs。
  • 通訊資源管理器(Communication Resource Manager,簡稱CRM):控制一個TM域(TM domain)內或者跨TM域的分佈式應用之間的通訊。
  • 通訊協議(Communication Protocol,簡稱CP):一種通訊協議,它提供分佈式應用程序使用的、由CRMs支持的底層通訊服務。

介紹完模型元素,下面來看2種典型的DTP場景,一種是單應用跨庫DTP,另外一種是跨應用DTP。

3.1.2 單應用跨庫DTP

 一個應用使用一個事務管理器TM,操做多個資源管理器RMs,以下圖:

3.1.3 跨應用DTP

若是分佈式事務須要跨多個應用,例如微服務調用,那就必須增長通信資源管理器CRMs(跨應用管理事務),以下圖:

 

上圖中使用的接口以下:

  1. AP-RM接口 : 容許AP訪問資源,如SQL和ISAM,提供AP可移植性。
  2. AP-TM接口 : 即TX接口,爲AP提供了一個API, AP經過API與TM協調全局事務管理。
  3. TM-RM接口 : 即XA接口,容許TM將RMs的工做構造爲全局事務,並協調完成或恢復。XA接口是TM與RM之間的雙向接口。
  4. TM-CRM接口 : 即XA+接口,支持跨TM域的全局事務信息流。XA+ 接口是TM與CRM之間的雙向接口。
  5. AP-CRM接口 : 爲全局事務中的多應用之間的DTP通訊提供了可移植的api,例如:TxRPC、XATMI、Peer-to-Peer。
  6. CRM-OSI TP接口 : 即XAP-TP接口,提供了CRM和OSITP(Open Systems Interconnection — Distributed Transaction Processing)服務之間的編程接口。X/Open定義了這個接口來支持特定於應用程序的OSI服務的可移植實現。

本節咱們剖析了DTP模型,以及XA接口在DTP中的做用,下面咱們來更詳細的看一下XA規範。

3.2 XA規範

經過上面的分析,咱們知道XA和XA+規範的使用場景,以下圖所示:

下面來具體看一下XA/XA+接口定義的函數羣。其中帶+號的是XA+規範,不帶+號的是XA規範。

3.2.1 xa_*()函數羣

TM經過xa_*()函數調用RM。當AP調用TM啓動全局事務時,TM可使用xa_interface通知事務分支的RMs。AP使用RM的本機接口完成支持全局事務的工做後,TM調用xa_()函數提交或回滾分支。xa_()函數以下表所示:

3.2.2 ax_*()函數羣

RM經過ax_*()函數調用TM。全部的TMs都必須提供這些功能。這些函數容許RM動態地控制它在事務分支中的參與。此外,CRMs使用ax_interface建立事務分支,掛起或完成事務分支,並將承諾協議傳播到事務分支。ax_()函數以下表所示:

關於XA/XA+的具體方法如何調用流程這裏就再也不提供。有興趣的本身看規範原文。

3.3 兩階段提交-2PC

XA協議中有一個細節:按照OSITP標準(模型)的定義,TMs和RMs使用兩階段提交全局事務。

3.3.1 XA的兩階段提交模型

如上圖,XA規範實現的兩階段提交流程:(下面所有翻譯自XA規範原文)

階段1

  TM要求全部RMs準備提交(或準備)事務分支。這詢問RM是否可以保證提交事務分支的能力。RM可能會查詢該RM內部的其餘實例。CRM被要求準備它們建立的事務分支,將prepare請求發送到遠程站點並接收結果。在返回失敗並回滾其工做以後,RM能夠丟棄事務分支的信息。

階段2

  TM根據實際狀況向全部RMs發出提交或回滾事務分支的請求。CRM被要求提交或回滾它們建立的事務分支,向遠程站點發送提交或回滾請求並接收結果。全部RMs提交或回滾對共享資源的更改,而後將狀態返回給TM。而後TM能夠丟棄全局事務的信息。

3.3.2 XA對2PC的優化

1.只讀斷言

  當事務分支沒有更新共享資源時,這個RM會斷言並響應給TM的prepare請求。也就免去了階段2。可是,若是一個RM在全局事務的全部RMs返回prepared以前返回了只讀優化,該RM釋放事務上下文,例如read locks。這時候其餘事務就有機會去改變這些數據(多是寫鎖),顯然全局序列化被破壞。一樣CRM也能夠斷言,當TM掛起或終止線程與事務分支的關聯時,它不是某個特定線程中活動的事務分支的參與者。

2.一階段提交

  若是一個TM知道DTP系統中只有一個RM在修改共享資源,那麼它可使用單階段提交。即TM免去了階段1的prepare,直接執行了階段2的commit。

3.3.3 2PC的缺點

1.資源阻塞

因爲協調者的重要性,一旦協調者TM發生故障。參與者RM會一直阻塞下去。尤爲在第二階段,協調者發生故障,那麼全部的參與者還都處於鎖定事務資源的狀態中,而沒法繼續完成事務操做。(若是是協調者掛掉,能夠從新選舉一個協調者,可是沒法解決由於協調者宕機致使的參與者處於阻塞狀態的問題)

2.數據不一致

在階段二,當協調者向參與者發送commit請求以後,發生了局部網絡異常或者在發送commit請求過程當中協調者發生了故障,致使只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求以後就會執行commit操做。可是其餘部分未接到commit請求的機器則沒法執行事務提交。因而整個分佈式系統便出現了數據不一致性的現象。

因爲二階段提交存在着這些缺陷,因此,研究者們在二階段提交的基礎上作了改進,提出了三階段提交。

3.4 三階段提交-3PC

3PC,即Three-phase commit protocol,由一個協調者領導事務(領頭人),和一組被指導的參與者(同夥)組成。協調者和參與者都有超時執行機制,以下圖:

階段1:

  【協調者】接收事務請求。若是此時出現故障,協調者將停止事務,不然,協調者發送一個canCommit給全部參與者,並切換到waiting狀態。

  【參與者】得到了canCommit的請求,若是贊成,它將向協調者發送Yes消息並切換到prepared狀態。不然它將發送No消息並停止。若是出現故障,它將移動到abort狀態。

階段2:

  【協調者】在一個時間段內,接收來自全部參與者的Yes消息,向全部參與者發送preCommit消息並切換到prepared狀態。若是出現故障、超時或協調者(prepared狀態)接收到No消息,將停止事務並向全部參與者發送abort消息。

  【參與者】收到preCommit消息,它將發送ACK消息並等待最後的提交或停止。若是接收到停止消息、失敗或等待提交的超時,它將停止。

階段3:

  【協調者】在收到來自大多數參與者的確認的狀況下,協調者切換到commit狀態。並向全部參與者發送doCommit請求。若是協調者在等待一個參與者的ack時超時了,它將停止事務。

  【參與者】參與者接收到doCommit請求以後,執行正式的事務提交,併發送ack給協調者。注:超時未收到消息,同樣會提交事務!!!!

3.5 總結

上面講解了2pc、xa、3pc,比較以下:

協議/優缺點 優勢 缺點
2PC 邏輯簡單,容易理解。

1.全程阻塞。例如:TM故障,RM阻塞資源。

2.網絡故障時,部分commit,數據一致性沒法保證。

XA(提交時使用2PC規範)

1.只讀斷言

2.可進化爲一階段提交

全局序列化被破壞。髒讀問題。
3PC

引入雙邊超時機制,避免阻塞。

1.須要3次請求返回,可能會有長延遲,性能低。

2.基於失敗-中止(fail-stop)模型,出現網絡問題,沒法恢復。

 

 

 

 

 

 

 

 

 

 

 

 

 

問題:

上面3種協議都沒法解決分佈式系統下的數據一致性問題,只有Paxos算法,才能完全解決該問題。paxos飛機票:底層算法系列:Paxos算法。具體實踐中,爲了提升可用性(性能)通常不多作到強一致性。且大批的技術先驅們已經總結出了一套理論,讓咱們有理可依。

4、CAP理論

2000年7月,Eric Brewer教授在ACM PODC會議上提出CAP猜測。Brewer認爲在設計一個大規模的分佈式系統時會遇到三個特性:一致性(consistency)、可用性(Availability)、分區容錯(partition-tolerance),而一個分佈式系統最多隻能知足其中的2項。2年後,麻省理工學院的Seth Gilbert和Nancy Lynch從理論上證實了CAP。以後,CAP理論正式成爲分佈式計算領域的公認定理。

1. 一致性(Consistency)

一致性指「all nodes see the same data at the same time」,即更新操做成功並返回客戶端完成後,全部節點在同一時間的數據徹底一致,不能存在中間狀態。

強一致性全部節點在同一時間的數據徹底一致,那麼稱之爲強一致性。

弱一致性:此外,若是容許存在部分數據不一致,那麼就稱之爲弱一致性。

最終一致性:若是容許存在中間狀態,只要求通過一段時間後,數據最終是一致的,則稱之爲最終一致性。

2. 可用性(Availability)

    可用性是指系統提供的服務必須一直處於可用的狀態,對於用戶的每個操做請求老是可以在有限的時間內返回結果。

3. 分區容錯性(Partition tolerance)

    分區容錯的意思是,節點間通訊可能失敗,仍然須要可以保證對外提供知足一致性和可用性的服務。

4.1 分析

首先咱們必須保證P(分區容錯性),才能稱之爲一個分佈式系統,所以只能在C(一致性)和A(可用性)之間尋求平衡。而前面咱們提到的X/Open XA 兩階段提交協議的分佈式事務方案,強調的就是一致性。而且因爲其阻塞執行效率低,且當網絡出現問題時也沒法真正保證數據一致性,實際應用的並很少。而基於BASE理論的柔性事務,強調的是可用性,目前大行其道,大部分互聯網公司採可能會優先採用這種方案。(有的同窗問爲啥不用paxos?實現過於複雜,且保證了強一致性,想想也知道性能會有損耗,因此通常也不用!)

5、BASE理論

2008年7月28日,eBay的架構師Dan Pritchett源於對大規模分佈式系統的實踐總結,在ACM上發表文章提出BASE理論。文章連接:https://queue.acm.org/detail.cfm?id=1394128

    BASE理論是對CAP理論的延伸,核心思想是即便沒法作到強一致性(Strong Consistency,CAP的一致性就是強一致性),但應用能夠採用適合的方式達到最終一致性(Eventual Consistency)。    

BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫。

    1. 基本可用(Basically Available)

        指分佈式系統在出現不可預知故障的時候,容許損失部分可用性。

    2. 軟狀態( Soft State)

        指容許系統中的數據存在中間狀態,並認爲該中間狀態的存在不會影響系統的總體可用性。

    3. 最終一致( Eventual Consistency)

        強調的是全部的數據更新操做,在通過一段時間的同步以後,最終都可以達到一個一致的狀態。

    BASE理論面向的是大型高可用可擴展的分佈式系統,和傳統的事物ACID特性是相反的。經過犧牲強一致性來得到可用性,容許數據在一段時間內是不一致的,但最終達到一致狀態。實際應用中,會在對數據庫操做進行本地事務(ACID特性)+Eventually consistent最終一致性(BASE理論)結合使用

那麼如何實現分佈式環境下數據的最終一致性呢?

6、最終一致性方案(柔性事務)

實踐中,有些高可用場景下,沒必要要強一致性,只須要最終一致性便可,這在業內稱呼爲"柔性事務",也就是最終一致性方案,是遵循BASE理論設計出來的。

6.1 正向冪等重試+反向異步回調(最大努力通知型)

對於某些非核心service,能夠採起正向重試機制。好比一個請求超時失敗了,能夠再重試請求幾回,一直到接收到成功返回或者達到重試次數爲止。注意這裏要保證接口的冪等性。即屢次調用結果同樣。

不少調用第三方的接口(好比徵信接口,耗時比較長),接口是異步回調型。請求方發送請求後,等待第三方異步回調本身的返回結果接口。

這兩種機制都是不可靠的,必要時刻能夠二者相結合使用。以下圖所示:

6.2 可靠消息最終一致異步確保型)

這裏不講解已支持分佈式事務的MQ.

可靠消息就是使用獨立的消息服務,使用「預發送機制」把消息提早入庫,業務肯定執行完畢,再修改消息狀態爲可發送,而後再發送消息給MQ,消費者再消費。

預發送機制

  若是先執行業務,再發消息(先發消息再執行業務也不行),入kafka,可能馬上就消費了。本地事務回滾是沒法回滾已發送到kafka的消息的。使用預發送機制,保證了消息服務DB中有一條「初始化」狀態的消息記錄。業務異常,就不會「確認發送Msg」,消息就不會發送。

可靠場景下,甚至能夠在消息服務中輪詢」初始化「狀態的且過了「一個時間段」(通常超過這個時間,確定是出問題了)的消息,再去查詢業務系統是否完成,若是完成則自修覆成"待發送"狀態。

注:上圖主業務做爲生產者,嚴格來講,消息服務平臺纔是生產者(若是把kafka做爲中心的話)。

整個流程如上圖:

  1. 消息入庫:主業務系統,初始化一條消息進msg表,state=初始化。
  2. 確承認發送:更新消息狀態state=待發送。
  3. send生產消息:定時輪詢state=待發送 的消息,send給kafka。
  4. pull消費消息:從業務做爲消費者主動去kafka 拉取消息消費。
  5. ack告知kafka:消費成功告知kafka。
  6. 告知消息服務:消費成功告知消息服務,更新狀態state=完成,或者刪除消息記錄。(若是場景要求較高建議留下存根)

 本地消息表(業務系統+消息表,強一致性)

  若是不使用獨立的消息服務平臺,在業務系統內部新建一張消息表,就能夠徹底由一個本地事務來控制,這樣第一、2步的「消息入庫」、「確認發送」能夠確保成功,也就不須要「輪詢自修復」了,若是公司不要求使用統一消息服務平臺的話,使用本地消息表也是ok的。

6.3 TCC(兩階段補償型)

TCC 其實就是採用的補償機制,其核心思想是:針對每一個操做,都要註冊一個與其對應的確認和補償(撤銷)操做。TCC 實質上是應用層的2PC(2 PhaseCommit, 兩階段提交),比如把 XA 兩階段提交那種在數據資源層作的事務管理工做提到了數據應用層。TCC流程以下圖:

如上圖所示,步驟:

  • 階段1

    主業務活動請求(try)各個從業務服務預留資源。try過程的本地事務,是保證資源預留的業務邏輯的正確性。

  • 階段2

    若是在第一階段全部業務資源都預留成功,那麼confirm各個從業務服務,不然取消(cancel)全部從業務服務的資源預留請求。

優勢:

相比XA是資源層面的分佈式事務,強一致性,在兩階段提交的整個過程當中,一直會持有資源的鎖。

TCC是業務層面的分佈式事務,最終一致性,不會一直持有資源的鎖。confirm/cancel執行的本地事務邏輯確認/取消預留資源,confirm和cancel就是補償型事務(Compensation-Based Transactions)。注意:confirm和cancel都是獨立的本地事務,是對try的補償。

缺點:

針對一個請求,須要從業務服務提供3個接口,供主業務服務調用,業務方改形成本高。

 

====參考=======

分佈式事務 :第一節不少都是參考本文,寫的不錯。

相關文章
相關標籤/搜索