Java中的事務(wù)——全局事務(wù)與本地事務(wù)
在上一篇文章中說到過,Java事務(wù)的類型有三種:JDBC事務(wù)、JTA(Java Transaction API)事務(wù)、容器事務(wù)。這是從事務(wù)的實(shí)現(xiàn)角度區(qū)分的,本文從另外一個角度來再次區(qū)分一下Java中的事務(wù)。
站在事務(wù)管理的角度,可以把Java中用到的事務(wù)分為本地事務(wù)和全局事務(wù)。
本地事務(wù)
不用事務(wù)的編程框架來管理事務(wù),直接使用資源管理器來控制事務(wù)。典型的就是java.sql.Connection 中的 setAutoCommit、commit、rollback方法。
本地事務(wù)的優(yōu)點(diǎn)
- 支持嚴(yán)格的ACID屬性
- 可靠
- 高效
- 狀態(tài)可以只在資源管理器中維護(hù)
- 應(yīng)用編程模型簡單
本地事務(wù)的局限
- 不具備分布式事務(wù)處理能力
- 隔離的最小單位由資源管理器決定,如數(shù)據(jù)庫中的一條記錄
本地事務(wù)比較簡單,對事務(wù)不太了解的同學(xué)可以閱讀我的博客中其他關(guān)于事務(wù)的內(nèi)容。
全局事務(wù)
前面我們介紹了本地事務(wù),本地事務(wù)是我們在編程中比較常接觸的事務(wù),比如典型的jdbc操作,在保證ACID方面做的非常出色。但是本地事務(wù)無法解決分布式場景中的事務(wù)問題。
我前面的文章中專門介紹過分布式場景中為什么需要事務(wù)。這里我再稍微回顧一下。
典型的分布式事務(wù)場景
- 轉(zhuǎn)賬
對于銀行賬戶間轉(zhuǎn)賬的問題。賬戶A向賬戶B轉(zhuǎn)賬,從實(shí)現(xiàn)上來看,一般可以拆分為“從賬戶A中扣錢”、“向賬戶B中加錢”兩個操作步驟,兩個賬戶大多數(shù)情況下會被切分到不同的數(shù)據(jù)庫上,更多的是,兩個操作會是兩次服務(wù)調(diào)用。這兩個操作要求做到要么同時成功、要么同時失敗。因此引入了分布式事務(wù)問題。
- 下單
在電商網(wǎng)站上,在消費(fèi)者點(diǎn)擊購買按鈕后,交易后臺會進(jìn)行庫存檢查、下單、減庫存、更新訂單狀態(tài)等一連串的服務(wù)調(diào)用,每一個操作對應(yīng)一個獨(dú)立的服務(wù),服務(wù)一般會有獨(dú)立的數(shù)據(jù)庫,因此會產(chǎn)生分布式事務(wù)問題。
由于用一次操作,數(shù)據(jù)要寫入的數(shù)據(jù)庫不一致,或者調(diào)用的服務(wù)都是RPC服務(wù),那么就會無法保證操作在同一個事務(wù)中被處理掉。所以就會存在分布式的事務(wù)問題。
全局事務(wù)的定義
在上面的場景中會出現(xiàn)分布式事務(wù)問題,那么全局事務(wù)就是一個標(biāo)準(zhǔn)的分布式事務(wù)。下面我們嘗試著給全局事務(wù)下一個定義:
全局事務(wù)是由資源管理器管理和協(xié)調(diào)的事務(wù)。
全局事務(wù)是一個DTP模型的事務(wù),所謂DTP模型指的是X/Open DTP(X/Open Distributed Transaction Processing Reference Model),是X/Open 這個組織定義的一套分布式事務(wù)的標(biāo)準(zhǔn),也就是了定義了規(guī)范和API接口,由這個廠商進(jìn)行具體的實(shí)現(xiàn)。
X/Open DTP 定義了三個組件:AP,TM,RM 和兩個協(xié)議:XA、TX
AP(Application Program):也就是應(yīng)用程序,可以理解為使用DTP的程序
RM(Resource Manager):資源管理器,這里可以理解為一個DBMS系統(tǒng),或者消息服務(wù)器管理系統(tǒng),應(yīng)用程序通過資源管理器對資源進(jìn)行控制。
TM(Transaction Manager):事務(wù)管理器,負(fù)責(zé)協(xié)調(diào)和管理事務(wù),提供給AP應(yīng)用程序編程接口以及管理資源管理器。
XA協(xié)議:應(yīng)用或應(yīng)用服務(wù)器與事務(wù)管理之前通信的接口
TX協(xié)議:全局事務(wù)管理器與資源管理器之間通信的接口
事務(wù)管理器控制著全局事務(wù),管理事務(wù)生命周期,并協(xié)調(diào)資源。資源管理器負(fù)責(zé)控制和管理實(shí)際資源。
這里還要提到一個點(diǎn),就是2PC(兩階段提交),在全局事務(wù)中,為了保證所有的操作可以一次性要么全提交,要么全失敗。事務(wù)管理器和資源管理器之間的事務(wù)操作的控制是采用2PC來進(jìn)行的,關(guān)于2PC,我博客中有文章專門介紹,這里不再贅述。
J2EE中全局事務(wù)的實(shí)現(xiàn)
Java自身提供了一些API可以用來實(shí)現(xiàn)全局事務(wù)。Java中的事務(wù)——JDBC事務(wù)和JTA事務(wù)中介紹的JTA事務(wù)就可以用來實(shí)現(xiàn)J2EE中的全局事務(wù)。
JTA(Java Transaction API):面向應(yīng)用、應(yīng)用服務(wù)器與資 源管理器的高層事務(wù)接口。
JTS(Java Transaction Service):JTA事務(wù)管理器的實(shí)現(xiàn)標(biāo) 準(zhǔn),向上支持JTA,向下通過CORBA OTS實(shí)現(xiàn)跨事務(wù)域的互 操作性。
EJB:基于組件的應(yīng)用編程模型,通過聲明式事務(wù)管理進(jìn)一步 簡化事務(wù)應(yīng)用的編程。
全局事務(wù)的優(yōu)缺點(diǎn)
全局事務(wù),作為一種標(biāo)準(zhǔn)的分布式事務(wù)解決方案,他解決了本地事務(wù)無法滿足分布式場景中數(shù)據(jù)的ACID的要求。
在關(guān)于分布式事務(wù)、兩階段提交協(xié)議、三階提交協(xié)議中我曾經(jīng)介紹過,2PC本身是存在同步阻塞問題,這就會導(dǎo)致效率變低,所以,采用2PC進(jìn)行事務(wù)控制的全局事務(wù)也必然存在效率低的問題。這也是全局事務(wù)最致命的缺點(diǎn),在提倡微服務(wù)的今天,這是不能容忍的。
總結(jié)
本文主要介紹了本地事務(wù)和全局事務(wù),本地事務(wù)很簡單,在Java中可以使用JDBC來實(shí)現(xiàn)本地事務(wù),全局事務(wù)是一種基本的分布式事務(wù)解決方案,是符合DTP模型的事務(wù)管理機(jī)制。
目前,越來越多的web開發(fā)要涉及到分布式事務(wù),尤其是微服務(wù)架構(gòu)最近越來越火,在微服務(wù)架構(gòu)中,分布式事務(wù)是必然存在的。對于分布式事務(wù)的處理,本文主要介紹了一個典型的方案——全局事務(wù)。但是實(shí)際上,低效率的全局事務(wù)并不是很適合用來解決大型網(wǎng)站的分布式事務(wù)問題。
在業(yè)內(nèi),主要用來解決分布式事務(wù)的方案是使用柔性事務(wù)。柔性事務(wù)包括幾種類型:兩階段型、補(bǔ)償型、異步確保型和***努力通知型。后面我會有文章繼續(xù)介紹柔性事務(wù)。請繼續(xù)關(guān)注。
【本文是51CTO專欄作者Hollis的原創(chuàng)文章,作者微信公眾號Hollis(ID:hollischuang)】