小螞蟻說:
分布式事務(wù)是企業(yè)集成中的一個(gè)技術(shù)難點(diǎn),也是每一個(gè)分布式系統(tǒng)架構(gòu)中都會涉及到的一個(gè)東西,特別是在這幾年越來越火的微服務(wù)架構(gòu)中,幾乎可以說是無法避免,本文就圍繞分布式事務(wù)各方面與大家進(jìn)行介紹。
一. 事務(wù)
1.1 什么是事務(wù)
數(shù)據(jù)庫事務(wù)(簡稱:事務(wù),Transaction)是指數(shù)據(jù)庫執(zhí)行過程中的一個(gè)邏輯單位,由一個(gè)有限的數(shù)據(jù)庫操作序列構(gòu)成。
事務(wù)擁有以下四個(gè)特性,習(xí)慣上被稱為ACID特性:
原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行,包含在其中的對數(shù)據(jù)庫的操作要么全部被執(zhí)行,要么都不執(zhí)行。
一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫的狀態(tài)從一個(gè)一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致狀態(tài)。一致狀態(tài)是指數(shù)據(jù)庫中的數(shù)據(jù)應(yīng)滿足完整性約束。除此之外,一致性還有另外一層語義,就是事務(wù)的中間狀態(tài)不能被觀察到(這層語義也有說應(yīng)該屬于原子性)。
隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行,如同只有這一個(gè)操作在被數(shù)據(jù)庫所執(zhí)行一樣。
持久性(Durability):已被提交的事務(wù)對數(shù)據(jù)庫的修改應(yīng)該永久保存在數(shù)據(jù)庫中。在事務(wù)結(jié)束時(shí),此操作將不可逆轉(zhuǎn)。
1.2 本地事務(wù)
起初,事務(wù)僅限于對單一數(shù)據(jù)庫資源的訪問控制:
架構(gòu)服務(wù)化以后,事務(wù)的概念延伸到了服務(wù)中。倘若將一個(gè)單一的服務(wù)操作作為一個(gè)事務(wù),那么整個(gè)服務(wù)操作只能涉及一個(gè)單一的數(shù)據(jù)庫資源:
這類基于單個(gè)服務(wù)單一數(shù)據(jù)庫資源訪問的事務(wù),被稱為本地事務(wù)(Local Transaction)。
二. 分布式事務(wù)應(yīng)用架構(gòu)
本地事務(wù)主要限制在單個(gè)會話內(nèi),不涉及多個(gè)數(shù)據(jù)庫資源。但是在基于SOA(Service-Oriented Architecture,面向服務(wù)架構(gòu))的分布式應(yīng)用環(huán)境下,越來越多的應(yīng)用要求對多個(gè)數(shù)據(jù)庫資源,多個(gè)服務(wù)的訪問都能納入到同一個(gè)事務(wù)當(dāng)中,分布式事務(wù)應(yīng)運(yùn)而生。
最早的分布式事務(wù)應(yīng)用架構(gòu)很簡單,不涉及服務(wù)間的訪問調(diào)用,僅僅是服務(wù)內(nèi)操作涉及到對多個(gè)數(shù)據(jù)庫資源的訪問。
當(dāng)一個(gè)服務(wù)操作訪問不同的數(shù)據(jù)庫資源,又希望對它們的訪問具有事務(wù)特性時(shí),就需要采用分布式事務(wù)來協(xié)調(diào)所有的事務(wù)參與者。
對于上面介紹的分布式事務(wù)應(yīng)用架構(gòu),盡管一個(gè)服務(wù)操作會訪問多個(gè)數(shù)據(jù)庫資源,但是畢竟整個(gè)事務(wù)還是控制在單一服務(wù)的內(nèi)部。如果一個(gè)服務(wù)操作需要調(diào)用另外一個(gè)服務(wù),這時(shí)的事務(wù)就需要跨越多個(gè)服務(wù)了。在這種情況下,起始于某個(gè)服務(wù)的事務(wù)在調(diào)用另外一個(gè)服務(wù)的時(shí)候,需要以某種機(jī)制流轉(zhuǎn)到另外一個(gè)服務(wù),從而使被調(diào)用的服務(wù)訪問的資源也自動加入到該事務(wù)當(dāng)中來。下圖反映了這樣一個(gè)跨越多個(gè)服務(wù)的分布式事務(wù):
如果將上面這兩種場景(一個(gè)服務(wù)可以調(diào)用多個(gè)數(shù)據(jù)庫資源,也可以調(diào)用其他服務(wù))結(jié)合在一起,對此進(jìn)行延伸,整個(gè)分布式事務(wù)的參與者將會組成如下圖所示的樹形拓?fù)浣Y(jié)構(gòu)。在一個(gè)跨服務(wù)的分布式事務(wù)中,事務(wù)的發(fā)起者和提交均系同一個(gè),它可以是整個(gè)調(diào)用的客戶端,也可以是客戶端最先調(diào)用的那個(gè)服務(wù)。
較之基于單一數(shù)據(jù)庫資源訪問的本地事務(wù),分布式事務(wù)的應(yīng)用架構(gòu)更為復(fù)雜。在不同的分布式應(yīng)用架構(gòu)下,實(shí)現(xiàn)一個(gè)分布式事務(wù)要考慮的問題并不完全一樣,比如對多資源的協(xié)調(diào)、事務(wù)的跨服務(wù)傳播等,實(shí)現(xiàn)機(jī)制也是復(fù)雜多變。盡管有這么多工程細(xì)節(jié)需要考慮,但分布式事務(wù)最核心的還是其 ACID 特性。因此,想要了解一個(gè)分布式事務(wù),就先從了解它是怎么實(shí)現(xiàn)事務(wù) ACID 特性開始。
下文將從兩個(gè)最常見的分布式事務(wù)模型入手,著重分析分布式事務(wù)的基礎(chǔ)共通點(diǎn),即如何保證分布式事務(wù)的 ACID 特性。
三. 常見分布式事務(wù)模型 ACID 實(shí)現(xiàn)分析
3.1 X/Open XA 協(xié)議
最早的分布式事務(wù)模型是 X/Open 國際聯(lián)盟提出的 X/Open Distributed Transaction Processing(DTP)模型,也就是大家常說的 X/Open XA 協(xié)議,簡稱XA 協(xié)議。
DTP 模型中包含一個(gè)全局事務(wù)管理器(TM,Transaction Manager)和多個(gè)資源管理器(RM,Resource Manager)。全局事務(wù)管理器負(fù)責(zé)管理全局事務(wù)狀態(tài)與參與的資源,協(xié)同資源一起提交或回滾;資源管理器則負(fù)責(zé)具體的資源操作。
XA 協(xié)議描述了 TM 與 RM 之間的接口,允許多個(gè)資源在同一分布式事務(wù)中訪問。
基于 DTP 模型的分布式事務(wù)流程大致如下:
1.應(yīng)用程序(AP,Application)向 TM 申請開始一個(gè)全局事務(wù)。
2.針對要操作的 RM,AP 會先向 TM 注冊(TM 負(fù)責(zé)記錄 AP 操作過哪些 RM,即分支事務(wù)),TM 通過 XA 接口函數(shù)通知相應(yīng) RM 開啟分布式事務(wù)的子事務(wù),接著 AP 就可以對該 RM 管理的資源進(jìn)行操作。
3.當(dāng) AP 對所有 RM 操作完畢后,AP 根據(jù)執(zhí)行情況通知 TM 提交或回滾該全局事務(wù),TM 通過 XA 接口函數(shù)通知各 RM 完成操作。TM 會先要求各個(gè) RM 做預(yù)提交,所有 RM 返回成功后,再要求各 RM 做正式提交,XA 協(xié)議要求,一旦 RM 預(yù)提交成功,則后續(xù)的正式提交也必須能成功;如果任意一個(gè) RM 預(yù)提交失敗,則 TM 通知各 RM 回滾。
4.所有 RM 提交或回滾完成后,全局事務(wù)結(jié)束。
3.1.1 原子性
XA 協(xié)議使用 2PC(Two Phase Commit,兩階段提交)原子提交協(xié)議來保證分布式事務(wù)原子性。
兩階段提交是指將提交過程分為兩個(gè)階段,即準(zhǔn)備階段(投票階段)和提交階段(執(zhí)行階段):
準(zhǔn)備階段:
TM 向每個(gè) RM 發(fā)送準(zhǔn)備消息。如果 RM 的本地事務(wù)操作執(zhí)行成功,則返回成功;如果 RM 的本地事務(wù)操作執(zhí)行失敗,則返回失敗。
提交階段
如果 TM 收到了所有 RM 回復(fù)的成功消息,則向每個(gè) RM 發(fā)送提交消息;否則發(fā)送回滾消息;RM 根據(jù) TM 的指令執(zhí)行提交或者回滾本地事務(wù)操作,釋放所有事務(wù)處理過程中使用的鎖資源。
3.1.2 隔離性
XA 協(xié)議中沒有描述如何實(shí)現(xiàn)分布式事務(wù)的隔離性,但是 XA 協(xié)議要求DTP 模型中的每個(gè) RM 都要實(shí)現(xiàn)本地事務(wù),也就是說,基于 XA 協(xié)議實(shí)現(xiàn)的分布式事務(wù)的隔離性是由每個(gè) RM 本地事務(wù)的隔離性來保證的,當(dāng)一個(gè)分布式事務(wù)的所有子事務(wù)都是隔離的,那么這個(gè)分布式事務(wù)天然的就實(shí)現(xiàn)了隔離性。
以 MySQL 來舉例,MySQL 使用 2PL(Two-Phase Locking,兩階段鎖)機(jī)制來控制本地事務(wù)的并發(fā),保證隔離性。2PL 與 2PC 類似,也是將鎖操作分為加鎖和解鎖兩個(gè)階段,并且保證兩個(gè)階段完全不相交。加鎖階段,只加鎖,不放鎖。解鎖階段,只放鎖,不加鎖。
如上圖所示,在一個(gè)本地事務(wù)中,每執(zhí)行一條更新操作之前,都會先獲取對應(yīng)的鎖資源,只有獲取鎖資源成功才會執(zhí)行該操作,并且一旦獲取了鎖資源就會持有該鎖資源直到本事務(wù)執(zhí)行結(jié)束。
MySQL 通過這種 2PL 機(jī)制,可以保證在本地事務(wù)執(zhí)行過程中,其他并發(fā)事務(wù)不能操作相同資源,從而實(shí)現(xiàn)了事務(wù)隔離。
3.1.3 一致性
前面提到一致性有兩層語義,一層是確保事務(wù)執(zhí)行結(jié)束后,數(shù)據(jù)庫從一個(gè)一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致狀態(tài)。另一層語義是事務(wù)執(zhí)行過程中的中間狀態(tài)不能被觀察到。
前一層語義的實(shí)現(xiàn)很簡單,通過原子性、隔離性以及 RM 自身一致性的實(shí)現(xiàn)就可以保證。至于后一層語義,我們先來看看單個(gè) RM 上的本地事務(wù)是怎么實(shí)現(xiàn)的。還是以 MySQL 舉例,MySQL 通過 MVCC(Multi Version Concurrency Control,多版本并發(fā)控制)機(jī)制,為每個(gè)一致性狀態(tài)生成快照(Snapshot),每個(gè)事務(wù)看到的都是各Snapshot對應(yīng)的一致性狀態(tài),從而也就保證了本地事務(wù)的中間狀態(tài)不會被觀察到。
雖然單個(gè) RM 上實(shí)現(xiàn)了Snapshot,但是在分布式應(yīng)用架構(gòu)下,會遇到什么問題呢?
如上圖所示,在 RM1 的本地子事務(wù)提交完畢到 RM2 的本地子事務(wù)提交完畢之間,只能讀到 RM1 上子事務(wù)執(zhí)行的內(nèi)容,讀不到 RM2 上的子事務(wù)。也就是說,雖然在單個(gè) RM 上的本地事務(wù)是一致的,但是從全局來看,一個(gè)全局事務(wù)執(zhí)行過程的中間狀態(tài)被觀察到了,全局一致性就被破壞了。
XA 協(xié)議并沒有定義怎么實(shí)現(xiàn)全局的 Snapshot,像 MySQL 官方文檔里就建議使用串行化的隔離級別來保證分布式事務(wù)一致性: “As with nondistributed transactions, SERIALIZABLE may be preferred if your applications are sensitive to read phenomena. REPEATABLE READ may not be sufficient for distributed transactions.”(對于分布式事務(wù)來說,可重復(fù)讀隔離級別不足以保證事務(wù)一致性,如果你的程序有全局一致性讀要求,可以考慮串行化隔離級別.)
當(dāng)然,由于串行化隔離級別的性能較差,所以很多分布式數(shù)據(jù)庫都自己實(shí)現(xiàn)了分布式 MVCC 機(jī)制來提供全局的一致性讀。一個(gè)基本思路是用一個(gè)集中式或者邏輯上單調(diào)遞增的東西來控制生成全局 Snapshot,每個(gè)事務(wù)或者每條 SQL 執(zhí)行時(shí)都去獲取一次,從而實(shí)現(xiàn)不同隔離級別下的一致性。比如 Google 的 Spanner 就是用 TrueTime 來控制訪問全局 Snapshot。
3.1.4 小結(jié)
XA 協(xié)議通常實(shí)現(xiàn)在數(shù)據(jù)庫資源層,直接作用于資源管理器上。因此,基于 XA 協(xié)議實(shí)現(xiàn)的分布式事務(wù)產(chǎn)品,無論是分布式數(shù)據(jù)庫,還是分布式事務(wù)框架,對業(yè)務(wù)幾乎都沒有侵入,就像使用普通數(shù)據(jù)庫一樣。
XA 協(xié)議嚴(yán)格保障事務(wù) ACID 特性,能夠滿足所有業(yè)務(wù)領(lǐng)域的功能需求,但是,這同樣是一把雙刃劍。
由于隔離性的互斥要求,在事務(wù)執(zhí)行過程中,所有的資源都被鎖定,只適用于執(zhí)行時(shí)間確定的短事務(wù)。同時(shí),整個(gè)事務(wù)期間都是獨(dú)占數(shù)據(jù),對于熱點(diǎn)數(shù)據(jù)的并發(fā)性能可能會很低,實(shí)現(xiàn)了分布式 MVCC 或樂觀鎖(optimistic locking)以后,性能可能會有所提升。
同時(shí),為了保障一致性,要求所有 RM 同等可信、可靠,要求故障恢復(fù)機(jī)制可靠、快速,在網(wǎng)絡(luò)故障隔離的情況下,服務(wù)基本不可用。
3.2 TCC 模型
TCC(Try-Confirm-Cancel)分布式事務(wù)模型相對于 XA 等傳統(tǒng)模型,其特征在于它不依賴資源管理器(RM)對分布式事務(wù)的支持,而是通過對業(yè)務(wù)邏輯的分解來實(shí)現(xiàn)分布式事務(wù)。
TCC 模型認(rèn)為對于業(yè)務(wù)系統(tǒng)中一個(gè)特定的業(yè)務(wù)邏輯,其對外提供服務(wù)時(shí),必須接受一些不確定性,即對業(yè)務(wù)邏輯初步操作的調(diào)用僅是一個(gè)臨時(shí)性操作,調(diào)用它的主業(yè)務(wù)服務(wù)保留了后續(xù)的取消權(quán)。如果主業(yè)務(wù)服務(wù)認(rèn)為全局事務(wù)應(yīng)該回滾,它會要求取消之前的臨時(shí)性操作,這就對應(yīng)從業(yè)務(wù)服務(wù)的取消操作。而當(dāng)主業(yè)務(wù)服務(wù)認(rèn)為全局事務(wù)應(yīng)該提交時(shí),它會放棄之前臨時(shí)性操作的取消權(quán),這對應(yīng)從業(yè)務(wù)服務(wù)的確認(rèn)操作。每一個(gè)初步操作,最終都會被確認(rèn)或取消。
因此,針對一個(gè)具體的業(yè)務(wù)服務(wù),TCC 分布式事務(wù)模型需要業(yè)務(wù)系統(tǒng)提供三段業(yè)務(wù)邏輯:
初步操作 Try:完成所有業(yè)務(wù)檢查,預(yù)留必須的業(yè)務(wù)資源。
確認(rèn)操作 Confirm:真正執(zhí)行的業(yè)務(wù)邏輯,不作任何業(yè)務(wù)檢查,只使用 Try 階段預(yù)留的業(yè)務(wù)資源。因此,只要 Try 操作成功,Confirm 必須能成功。另外,Confirm 操作需滿足冪等性,保證一筆分布式事務(wù)有且只能成功一次。
取消操作 Cancel:釋放 Try 階段預(yù)留的業(yè)務(wù)資源。同樣的,Cancel 操作也需要滿足冪等性。
TCC 分布式事務(wù)模型包括三部分:
主業(yè)務(wù)服務(wù):主業(yè)務(wù)服務(wù)為整個(gè)業(yè)務(wù)活動的發(fā)起方,服務(wù)的編排者,負(fù)責(zé)發(fā)起并完成整個(gè)業(yè)務(wù)活動。
從業(yè)務(wù)服務(wù):從業(yè)務(wù)服務(wù)是整個(gè)業(yè)務(wù)活動的參與方,負(fù)責(zé)提供 TCC 業(yè)務(wù)操作,實(shí)現(xiàn)初步操作(Try)、確認(rèn)操作(Confirm)、取消操作(Cancel)三個(gè)接口,供主業(yè)務(wù)服務(wù)調(diào)用。
業(yè)務(wù)活動管理器:業(yè)務(wù)活動管理器管理控制整個(gè)業(yè)務(wù)活動,包括記錄維護(hù) TCC 全局事務(wù)的事務(wù)狀態(tài)和每個(gè)從業(yè)務(wù)服務(wù)的子事務(wù)狀態(tài),并在業(yè)務(wù)活動提交時(shí)調(diào)用所有從業(yè)務(wù)服務(wù)的 Confirm 操作,在業(yè)務(wù)活動取消時(shí)調(diào)用所有從業(yè)務(wù)服務(wù)的 Cancel 操作。
一個(gè)完整的 TCC 分布式事務(wù)流程如下:
主業(yè)務(wù)服務(wù)首先開啟本地事務(wù);
主業(yè)務(wù)服務(wù)向業(yè)務(wù)活動管理器申請啟動分布式事務(wù)主業(yè)務(wù)活動;
然后針對要調(diào)用的從業(yè)務(wù)服務(wù),主業(yè)務(wù)活動先向業(yè)務(wù)活動管理器注冊從業(yè)務(wù)活動,然后調(diào)用從業(yè)務(wù)服務(wù)的 Try 接口;
當(dāng)所有從業(yè)務(wù)服務(wù)的 Try 接口調(diào)用成功,主業(yè)務(wù)服務(wù)提交本地事務(wù);若調(diào)用失敗,主業(yè)務(wù)服務(wù)回滾本地事務(wù);
若主業(yè)務(wù)服務(wù)提交本地事務(wù),則 TCC 模型分別調(diào)用所有從業(yè)務(wù)服務(wù)的 Confirm 接口;若主業(yè)務(wù)服務(wù)回滾本地事務(wù),則分別調(diào)用 Cancel 接口;
所有從業(yè)務(wù)服務(wù)的 Confirm 或 Cancel 操作完成后,全局事務(wù)結(jié)束。
3.2.1 原子性
TCC 模型也使用 2PC 原子提交協(xié)議來保證事務(wù)原子性。Try 操作對應(yīng)2PC 的一階段準(zhǔn)備(Prepare);Confirm 對應(yīng) 2PC 的二階段提交(Commit),Cancel 對應(yīng) 2PC 的二階段回滾(Rollback),可以說 TCC 就是應(yīng)用層的 2PC。
3.2.2 隔離性
TCC 分布式事務(wù)模型僅提供兩階段原子提交協(xié)議,保證分布式事務(wù)原子性。事務(wù)的隔離交給業(yè)務(wù)邏輯來實(shí)現(xiàn)。
隔離的本質(zhì)是控制并發(fā),防止并發(fā)事務(wù)操作相同資源而引起的結(jié)果錯亂。
舉個(gè)例子,比如金融行業(yè)里管理用戶資金,當(dāng)用戶發(fā)起交易時(shí),一般會先檢查用戶資金,如果資金充足,則扣除相應(yīng)交易金額,增加賣家資金,完成交易。如果沒有事務(wù)隔離,用戶同時(shí)發(fā)起兩筆交易,兩筆交易的檢查都認(rèn)為資金充足,實(shí)際上卻只夠支付一筆交易,結(jié)果兩筆交易都支付成功,導(dǎo)致資損。
可以發(fā)現(xiàn),并發(fā)控制是業(yè)務(wù)邏輯執(zhí)行正確的保證,但是像兩階段鎖這樣的并發(fā)訪問控制技術(shù)要求一直持有數(shù)據(jù)庫資源鎖直到整個(gè)事務(wù)執(zhí)行結(jié)束,特別是在分布式事務(wù)架構(gòu)下,要求持有鎖到分布式事務(wù)第二階段執(zhí)行結(jié)束,也就是說,分布式事務(wù)會加長資源鎖的持有時(shí)間,導(dǎo)致并發(fā)性能進(jìn)一步下降。
因此,TCC 模型的隔離性思想就是通過業(yè)務(wù)的改造,在第一階段結(jié)束之后,從底層數(shù)據(jù)庫資源層面的加鎖過渡為上層業(yè)務(wù)層面的加鎖,從而釋放底層數(shù)據(jù)庫鎖資源,放寬分布式事務(wù)鎖協(xié)議,提高業(yè)務(wù)并發(fā)性能。
還是以上面的例子舉例:
第一階段:檢查用戶資金,如果資金充足,凍結(jié)用戶本次交易資金,這筆資金被業(yè)務(wù)隔離,不允許除本事務(wù)之外的其它并發(fā)事務(wù)動用。
第二階段:扣除第一階段預(yù)凍結(jié)的用戶資金,增加賣家資金,完成交易。 采用業(yè)務(wù)加鎖的方式,隔離用戶凍結(jié)資金,在第一階段結(jié)束后直接釋放底層資源鎖,該用戶和賣家的其他交易都可以立刻并發(fā)執(zhí)行,而不用等到整個(gè)分布式事務(wù)結(jié)束,可以獲得更高的并發(fā)交易能力。
3.2.3 一致性
再來看看 TCC 分布式事務(wù)模型下的一致性實(shí)現(xiàn)。與 XA 協(xié)議實(shí)現(xiàn)一致性第一層語義類似,通過原子性保證事務(wù)的原子提交、業(yè)務(wù)隔離性控制事務(wù)的并發(fā)訪問,實(shí)現(xiàn)分布式事務(wù)的一致性狀態(tài)轉(zhuǎn)變。
至于第二層語義:事務(wù)的中間狀態(tài)不能被觀察到。我們來看看,在 SOA分布式應(yīng)用環(huán)境下是否是必須的。
還是以賬務(wù)服務(wù)舉例。轉(zhuǎn)賬業(yè)務(wù)(用戶 A ? 用戶 B),由交易服務(wù)和賬務(wù)服務(wù)組成分布式事務(wù),交易服務(wù)作為主業(yè)務(wù)服務(wù),賬務(wù)服務(wù)作為從業(yè)務(wù)服務(wù),賬務(wù)服務(wù)的 Try 操作預(yù)凍結(jié)用戶 A 的資金;Commit 操作扣除用戶 A 的預(yù)凍結(jié)資金,增加用戶 B 的可用資金;Cancel 操作解凍用戶 A 的預(yù)凍結(jié)資金。
當(dāng)賬務(wù)服務(wù)執(zhí)行完 Try 階段后,交易主業(yè)務(wù)就可以 Commit 了,然后由TCC 框架調(diào)用賬務(wù)的 Commit 階段。在賬務(wù) Commit 階段還沒執(zhí)行結(jié)束的時(shí)候,用戶 A 可以查詢到自己的余額已扣除,但是,此時(shí)用戶 B 的可用資金還沒增加。
從系統(tǒng)的角度來看,確實(shí)有問題與不確定性。在第一階段執(zhí)行結(jié)束到第二階段執(zhí)行結(jié)束之間,有一段時(shí)間的延時(shí),在這段時(shí)間內(nèi),看似任何用戶都不享有這筆資產(chǎn)。
但是,從用戶的角度來考慮這個(gè)問題的話,這個(gè)時(shí)間間隔可能就無所謂或者根本就不存在。特別是當(dāng)這個(gè)時(shí)間間隔僅僅是幾秒鐘,對于具體溝通資產(chǎn)轉(zhuǎn)移的用戶來講,這個(gè)過程是隱蔽的或確實(shí)可以接受的,且保證了結(jié)果的最終一致性。
當(dāng)然,對于這樣的系統(tǒng),如果確實(shí)需要查看系統(tǒng)的某個(gè)一致性狀態(tài),可以采用額外的方法實(shí)現(xiàn)。
一般來講,服務(wù)之間的一致性比服務(wù)內(nèi)部的一致性要更加容易弱化,這也是為什么 XA 等直接在資源層面上實(shí)現(xiàn)通用分布式事務(wù)的模型會注重一致性的保證,而當(dāng)上升到服務(wù)層面,服務(wù)與服務(wù)之間已經(jīng)實(shí)現(xiàn)了功能的劃分,邏輯的解耦,也就更容易弱化一致性,這就是 SOA 架構(gòu)下 BASE 理論的最終一致性思想。
BASE 理論是指 BA(Basic Availability,基本業(yè)務(wù)可用性);S(Soft state,柔性狀態(tài));E(Eventual consistency,最終一致性)。該理論認(rèn)為為了可用性、性能與降級服務(wù)的需要,可以適當(dāng)降低一點(diǎn)一致性的要求,即“基本可用,最終一致”。
業(yè)內(nèi)通常把嚴(yán)格遵循 ACID 的事務(wù)稱為剛性事務(wù);而基于 BASE 思想實(shí)現(xiàn)的事務(wù)稱為柔性事務(wù)。柔性事務(wù)并不是完全放棄了 ACID,僅僅是放寬了一致性要求:事務(wù)完成后的一致性嚴(yán)格遵循,事務(wù)中的一致性可適當(dāng)放寬;
3.2.4 小結(jié)
TCC 分布式事務(wù)模型的業(yè)務(wù)實(shí)現(xiàn)特性決定了其可以跨 DB、跨服務(wù)實(shí)現(xiàn)資源管理,將對不同的 DB 訪問、不同的業(yè)務(wù)操作通過 TCC 模型協(xié)調(diào)為一個(gè)原子操作,解決了分布式應(yīng)用架構(gòu)場景下的事務(wù)問題。
TCC 模型通過 2PC 原子提交協(xié)議保證分布式事務(wù)的的原子性,把資源層的隔離性上升到業(yè)務(wù)層,交給業(yè)務(wù)邏輯來實(shí)現(xiàn)。TCC 的每個(gè)操作對于資源層來說,就是單個(gè)本地事務(wù)的使用,操作結(jié)束則本地事務(wù)結(jié)束,規(guī)避了資源層在 2PC 和 2PL 下對資源占用導(dǎo)致的性能低下問題。
同時(shí),TCC 模型也可以根據(jù)業(yè)務(wù)需要,做一些定制化的功能,比如交易異步化實(shí)現(xiàn)削峰填谷等。
但是,業(yè)務(wù)接入 TCC 模型需要拆分業(yè)務(wù)邏輯成兩個(gè)階段,并實(shí)現(xiàn) Try、Confirm、Cancel 三個(gè)接口,定制化程度高,開發(fā)成本高。
四. 總結(jié)
本文首先介紹了典型的分布式事務(wù)的架構(gòu)場景。分布式事務(wù)剛開始是為解決單服務(wù)多數(shù)據(jù)庫資源的場景而誕生的。隨著技術(shù)的發(fā)展,特別是 SOA 分布式應(yīng)用架構(gòu)以及微服務(wù)時(shí)代的到來,服務(wù)變成了基本業(yè)務(wù)單元。因此,又產(chǎn)生了跨服務(wù)的分布式事務(wù)需求。然后從 XA 和 TCC 兩種常用的分布式事務(wù)模型入手,介紹了其實(shí)現(xiàn)機(jī)制,著重分析了各模型是如何實(shí)現(xiàn)分布式事務(wù) ACID 特性的。