分佈式事務(一)原理概覽html
分佈式事務(二)JTA規範java
分佈式事務(四)簡單樣例mysql
分佈式事務(六)總結提升spring
事務(數據庫事務)是java開發工程師必須掌握的一項技能。又可分爲本地事務和分佈式事務,其中分佈式事務是進階爲高級開發工程師必會的技能。本文從概念、原理、實踐多角度剖析分佈式事務,但願有所收穫。sql
大部分狀況下,一個服務操做一個數據庫,這就是本地事務,ACID特性由數據庫提供支持,好比mysql innodb引擎。以下圖所示(網上的圖,挺好直接用):數據庫
spring 提供了2種方式實現:編程
關於本地事務這裏很少說,飛機票:本地事務飛機票。api
當遇到複雜業務調用時,可能會出現跨庫多資源調用(一個事務管理器,多個資源)/多服務調用(多個事務管理器,多個資源),指望所有成功或失敗回滾,這就是分佈式事務,用以保證「操做多個隔離資源的數據一致性」。
Mysql官方對於XA事務,描述以下:
在open group官網可查到,有2個XA規範,一個是XA,一個是XA+, 其中XA+是XA的超集,新定義了通訊資源管理器CRM的協議,建議直接看XA+便可。後續分析直接以XA+ 1994版爲準。官方下載連接以下:
看名字咱們就知道 XA規範是依託於DTP場景的,下面咱們分別從DTP模型、XA規範2個視角來剖析原理。
依據X/Open《Distributed Transaction Processing: Reference Model, Version 3》上的介紹,DTP模型是一種軟件體系結構,它容許多個應用程序共享多個資源管理器提供的資源,並容許將它們的工做協調到全局事務中。
要深度瞭解DTP,先看看模型內的元素概念,以下:
介紹完模型元素,下面來看2種典型的DTP場景,一種是單應用跨庫DTP,另外一種是跨應用DTP。
一個應用使用一個事務管理器TM,操做多個資源管理器RMs,以下圖:
若是分佈式事務須要跨多個應用,例如微服務調用,那就必須增長通信資源管理器CRMs(跨應用管理事務),以下圖:
上圖中使用的接口以下:
本節咱們剖析了DTP模型,以及XA接口在DTP中的做用,下面咱們來更詳細的看一下XA規範。
經過上面的分析,咱們知道XA和XA+規範的使用場景,以下圖所示:
下面來具體看一下XA/XA+接口定義的函數羣。其中帶+號的是XA+規範,不帶+號的是XA規範。
TM經過xa_*()函數調用RM。當AP調用TM啓動全局事務時,TM可使用xa_interface通知事務分支的RMs。AP使用RM的本機接口完成支持全局事務的工做後,TM調用xa_()函數提交或回滾分支。xa_()函數以下表所示:
RM經過ax_*()函數調用TM。全部的TMs都必須提供這些功能。這些函數容許RM動態地控制它在事務分支中的參與。此外,CRMs使用ax_interface建立事務分支,掛起或完成事務分支,並將承諾協議傳播到事務分支。ax_()函數以下表所示:
關於XA/XA+的具體方法如何調用流程這裏就再也不提供。有興趣的本身看規範原文。
XA協議中有一個細節:按照OSITP標準(模型)的定義,TMs和RMs使用兩階段提交全局事務。
如上圖,XA規範實現的兩階段提交流程:(下面所有翻譯自XA規範原文)
階段1:
TM要求全部RMs準備提交(或準備)事務分支。這詢問RM是否可以保證提交事務分支的能力。RM可能會查詢該RM內部的其餘實例。CRM被要求準備它們建立的事務分支,將prepare請求發送到遠程站點並接收結果。在返回失敗並回滾其工做以後,RM能夠丟棄事務分支的信息。
階段2:
TM根據實際狀況向全部RMs發出提交或回滾事務分支的請求。CRM被要求提交或回滾它們建立的事務分支,向遠程站點發送提交或回滾請求並接收結果。全部RMs提交或回滾對共享資源的更改,而後將狀態返回給TM。而後TM能夠丟棄全局事務的信息。
1.只讀斷言
當事務分支沒有更新共享資源時,這個RM會斷言並響應給TM的prepare請求。也就免去了階段2。可是,若是一個RM在全局事務的全部RMs返回prepared以前返回了只讀優化,該RM釋放事務上下文,例如read locks。這時候其餘事務就有機會去改變這些數據(多是寫鎖),顯然全局序列化被破壞。一樣CRM也能夠斷言,當TM掛起或終止線程與事務分支的關聯時,它不是某個特定線程中活動的事務分支的參與者。
2.一階段提交
若是一個TM知道DTP系統中只有一個RM在修改共享資源,那麼它可使用單階段提交。即TM免去了階段1的prepare,直接執行了階段2的commit。
1.資源阻塞
因爲協調者的重要性,一旦協調者TM發生故障。參與者RM會一直阻塞下去。尤爲在第二階段,協調者發生故障,那麼全部的參與者還都處於鎖定事務資源的狀態中,而沒法繼續完成事務操做。(若是是協調者掛掉,能夠從新選舉一個協調者,可是沒法解決由於協調者宕機致使的參與者處於阻塞狀態的問題)
2.數據不一致
在階段二,當協調者向參與者發送commit請求以後,發生了局部網絡異常或者在發送commit請求過程當中協調者發生了故障,致使只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求以後就會執行commit操做。可是其餘部分未接到commit請求的機器則沒法執行事務提交。因而整個分佈式系統便出現了數據不一致性的現象。
因爲二階段提交存在着這些缺陷,因此,研究者們在二階段提交的基礎上作了改進,提出了三階段提交。
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給協調者。注:超時未收到消息,同樣會提交事務!!!!
上面講解了2pc、xa、3pc,比較以下:
協議/優缺點 | 優勢 | 缺點 |
2PC | 邏輯簡單,容易理解。 | 1.全程阻塞。例如:TM故障,RM阻塞資源。 2.網絡故障時,部分commit,數據一致性沒法保證。 |
XA(提交時使用2PC規範) | 1.只讀斷言 2.可進化爲一階段提交 |
全局序列化被破壞。髒讀問題。 |
3PC | 引入雙邊超時機制,避免阻塞。 |
1.須要3次請求返回,可能會有長延遲,性能低。 2.基於失敗-中止(fail-stop)模型,出現網絡問題,沒法恢復。 |
上面3種協議都沒法解決分佈式系統下的數據一致性問題,只有Paxos算法,才能完全解決該問題。paxos飛機票:底層算法系列:Paxos算法。具體實踐中,爲了提升可用性(性能)通常不多作到強一致性。且大批的技術先驅們已經總結出了一套理論,讓咱們有理可依。
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)
分區容錯的意思是,節點間通訊可能失敗,仍然須要可以保證對外提供知足一致性和可用性的服務。
首先咱們必須保證P(分區容錯性),才能稱之爲一個分佈式系統,所以只能在C(一致性)和A(可用性)之間尋求平衡。而前面咱們提到的X/Open XA 兩階段提交協議的分佈式事務方案,強調的就是一致性。而且因爲其阻塞執行效率低,且當網絡出現問題時也沒法真正保證數據一致性,實際應用的並很少。而基於BASE理論的柔性事務,強調的是可用性,目前大行其道,大部分互聯網公司採可能會優先採用這種方案。(有的同窗問爲啥不用paxos?實現過於複雜,且保證了強一致性,想想也知道性能會有損耗,因此通常也不用!)
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理論)結合使用。
那麼如何實現分佈式環境下數據的最終一致性呢?
實踐中,有些高可用場景下,沒必要要強一致性,只須要最終一致性便可,這在業內稱呼爲"柔性事務",也就是最終一致性方案,是遵循BASE理論設計出來的。
對於某些非核心service,能夠採起正向重試機制。好比一個請求超時失敗了,能夠再重試請求幾回,一直到接收到成功返回或者達到重試次數爲止。注意這裏要保證接口的冪等性。即屢次調用結果同樣。
不少調用第三方的接口(好比徵信接口,耗時比較長),接口是異步回調型。請求方發送請求後,等待第三方異步回調本身的返回結果接口。
這兩種機制都是不可靠的,必要時刻能夠二者相結合使用。以下圖所示:
這裏不講解已支持分佈式事務的MQ.
可靠消息就是使用獨立的消息服務,使用「預發送機制」把消息提早入庫,業務肯定執行完畢,再修改消息狀態爲可發送,而後再發送消息給MQ,消費者再消費。
預發送機制
若是先執行業務,再發消息(先發消息再執行業務也不行),入kafka,可能馬上就消費了。本地事務回滾是沒法回滾已發送到kafka的消息的。使用預發送機制,保證了消息服務DB中有一條「初始化」狀態的消息記錄。業務異常,就不會「確認發送Msg」,消息就不會發送。
可靠場景下,甚至能夠在消息服務中輪詢」初始化「狀態的且過了「一個時間段」(通常超過這個時間,確定是出問題了)的消息,再去查詢業務系統是否完成,若是完成則自修覆成"待發送"狀態。
注:上圖主業務做爲生產者,嚴格來講,消息服務平臺纔是生產者(若是把kafka做爲中心的話)。
整個流程如上圖:
本地消息表(業務系統+消息表,強一致性)
若是不使用獨立的消息服務平臺,在業務系統內部新建一張消息表,就能夠徹底由一個本地事務來控制,這樣第一、2步的「消息入庫」、「確認發送」能夠確保成功,也就不須要「輪詢自修復」了,若是公司不要求使用統一消息服務平臺的話,使用本地消息表也是ok的。
TCC 其實就是採用的補償機制,其核心思想是:針對每一個操做,都要註冊一個與其對應的確認和補償(撤銷)操做。TCC 實質上是應用層的2PC(2 PhaseCommit, 兩階段提交),比如把 XA 兩階段提交那種在數據資源層作的事務管理工做提到了數據應用層。TCC流程以下圖:
如上圖所示,步驟:
主業務活動請求(try)各個從業務服務預留資源。try過程的本地事務,是保證資源預留的業務邏輯的正確性。
若是在第一階段全部業務資源都預留成功,那麼confirm各個從業務服務,不然取消(cancel)全部從業務服務的資源預留請求。
優勢:
相比XA是資源層面的分佈式事務,強一致性,在兩階段提交的整個過程當中,一直會持有資源的鎖。
TCC是業務層面的分佈式事務,最終一致性,不會一直持有資源的鎖。confirm/cancel執行的本地事務邏輯確認/取消預留資源,confirm和cancel就是補償型事務
(Compensation-Based Transactions)。注意:confirm和cancel都是獨立的本地事務,是對try的補償。
缺點:
針對一個請求,須要從業務服務提供3個接口,供主業務服務調用,業務方改形成本高。
====參考=======
分佈式事務 :第一節不少都是參考本文,寫的不錯。