【网站架构】一招搞定90%的分布式事务,实打实介绍数据库事务、分布式事务的工作原理应用场景
大家好,歡迎來到停止重構(gòu)的頻道。本期,我們來聊一下數(shù)據(jù)庫事務(wù)以及分布式事務(wù)。
大家都在強(qiáng)調(diào)事務(wù)的重要性,而分布式事務(wù)也說是微服務(wù)必備的。但又說事務(wù)會影響性能,分布式事務(wù)更是很復(fù)雜的東西。使得大家都很迷茫什么時候才該用事務(wù),也不清楚什么場景下,分布式事務(wù)才是必要的。
接下來我們將會實(shí)打?qū)嵉赜懻搶?shí)際項目當(dāng)中,數(shù)據(jù)庫事務(wù)、分布式事務(wù)的工作原理以及相關(guān)的應(yīng)用場景。
事務(wù)說白了就是把多次數(shù)據(jù)操作打包成一次操作。要么操作都成功,要么都不執(zhí)行。而事務(wù)也分為兩種,我們也將對這兩種事務(wù)分別討論。
1、數(shù)據(jù)庫事務(wù),一般指的是單個數(shù)據(jù)庫的事務(wù)
2、分布式事務(wù),一般指的是多個數(shù)據(jù)庫的事務(wù)
數(shù)據(jù)庫事務(wù)
首先是數(shù)據(jù)庫事務(wù),數(shù)據(jù)庫事務(wù)是保證單個數(shù)據(jù)庫下多個數(shù)據(jù)表的數(shù)據(jù)一致性問題。也就是不會出現(xiàn)A表更新了數(shù)據(jù)而B表沒更新的狀況(要么都更新,要么都回滾)。
數(shù)據(jù)庫事務(wù)的工作原理是這樣的。請求端發(fā)送“開啟事務(wù)的SQL語句(begin)”到數(shù)據(jù)庫以開啟事務(wù)。
事務(wù)開啟期間,請求端可發(fā)送多條SQL語句以操作數(shù)據(jù)。數(shù)據(jù)庫會根據(jù)事務(wù)等級及相關(guān)的數(shù)據(jù)表或數(shù)據(jù)行阻塞其他數(shù)據(jù)操作(直到事務(wù)結(jié)束)。
操作完畢后,請求端可根據(jù)數(shù)據(jù)操作是否成功以及自身業(yè)務(wù)要求。決定發(fā)送“提交或回滾事務(wù)(commit/rollback)”的SQL語句,以告訴數(shù)據(jù)庫是否將之前操作成功的數(shù)據(jù)進(jìn)行回滾。
數(shù)據(jù)庫事務(wù)影響數(shù)據(jù)庫性能的原因有兩個:?
-
事務(wù)操作期間,可能會阻塞其他數(shù)據(jù)操作,具體需要根據(jù)事務(wù)等級、相關(guān)數(shù)據(jù)表或數(shù)據(jù)行而定;
-
若事務(wù)需要回滾,則一般會鎖表,阻塞所有操作相關(guān)表的數(shù)據(jù)操作。
數(shù)據(jù)庫事務(wù)雖然看上去很復(fù)雜,但是在實(shí)際開發(fā)過程中是簡單的。以Spring框架為例,在Service函數(shù)中添加事務(wù)注解即可,框架會根據(jù)數(shù)據(jù)操作是否出現(xiàn)exception(說明該次數(shù)據(jù)操作失敗)而決定是否回滾。
另外,事務(wù)等級是可以選擇的。但除非數(shù)據(jù)的讀一致性要求非常強(qiáng),如賬號余額檢驗(yàn)等場景。一般情況下,事務(wù)等級保持默認(rèn)就可以了。
那么什么時候使用數(shù)據(jù)庫事務(wù)呢,我們的推薦如下:
-
需要多次數(shù)據(jù)更新操作的接口,一般需要添加數(shù)據(jù)庫事務(wù)
-
?查詢與只更新一次數(shù)據(jù)的接口,且查詢的數(shù)據(jù)讀一致性要求非常強(qiáng),如賬號余額校驗(yàn)等場景。則一般添加數(shù)據(jù)庫事務(wù),且事務(wù)等級需要調(diào)到最高(性能影響也會更高)。
分布式事務(wù)
接下來是分布式事務(wù),分布式事務(wù)是解決多個數(shù)據(jù)庫的數(shù)據(jù)一致性問題。但分布式事務(wù)的實(shí)現(xiàn)方式是復(fù)雜的。
很多時候,分布式事務(wù)是沒有必要的。
例如,交易時需要同時操作余額數(shù)據(jù)庫與優(yōu)惠券數(shù)據(jù)庫。其實(shí)這是一種過度設(shè)計,完全沒必要分離出這兩個系統(tǒng)(合并成一個就可以了)。這也是大多數(shù)項目的現(xiàn)狀,子系統(tǒng)分得太碎了以至于出現(xiàn)很多的分布式事務(wù)問題。
又例如,博客編寫后,自動推送到某個活動專欄或者論壇。這種情況,也是沒有必要做分布式事務(wù)的。因?yàn)槿绻扑突顒踊蛘搲?#xff0c;博客仍應(yīng)該更新,而不能回滾。
其實(shí)這也說明了一個問題,數(shù)據(jù)庫事務(wù)與分布式事務(wù)的區(qū)別。除了單個數(shù)據(jù)庫與多個數(shù)據(jù)庫的區(qū)別,還有一個更加重要的區(qū)別:業(yè)務(wù)上的區(qū)別。?
一個數(shù)據(jù)庫內(nèi)的表是業(yè)務(wù)關(guān)聯(lián)性較強(qiáng)的,所以數(shù)據(jù)庫事務(wù)是頻繁的。但是多個數(shù)據(jù)庫間由于所屬的業(yè)務(wù)子系統(tǒng)是不一樣的,所以業(yè)務(wù)關(guān)聯(lián)性是不強(qiáng)的(數(shù)據(jù)不一致的要求不高)。自然需要分布式事務(wù)的場景其實(shí)也不多(過度設(shè)計除外)。
所以,大多數(shù)場景下,需要同時操作多個數(shù)據(jù)庫的話。一般前端整合多個子系統(tǒng)的API即可,或者由一個后端程序調(diào)用其他系統(tǒng)的API。
當(dāng)然,分布式事務(wù)的場景仍然是存在的。例如,訂單與庫存系統(tǒng)等。
下面我們開始介紹分布式事務(wù)的具體方法,分布式事務(wù)的理論做法有很多(如2PC、3PC、TCC、本地消息表等)。我們不一一介紹這些理論做法,只介紹實(shí)際項目中比較常用的幾種具體方法。
-
XA事務(wù)
-
Seata分布式事務(wù)框架
-
我們常用的流程方式
分布式事務(wù)方法:XA事務(wù)
首先是XA事務(wù),XA事務(wù)是數(shù)據(jù)庫原生支持的分布式事務(wù)(MySQL、Oracle都支持)。
XA事務(wù)的工作原理如圖所示,可以簡單地理解為同時執(zhí)行多個數(shù)據(jù)庫的數(shù)據(jù)庫事務(wù)。XA事務(wù)也有相關(guān)的操作框架,如JTA等。
?XA事務(wù)在實(shí)現(xiàn)上是相對簡單的(不需要使用其他中間件輔助),但在大型網(wǎng)站系統(tǒng)中,這種方式是不被提倡的。因?yàn)樗瑫r阻塞了多個數(shù)據(jù)庫(同時浪費(fèi)多個數(shù)據(jù)庫性能)。
同時,XA事務(wù)也意味著一個后端程序需要同時操作多個數(shù)據(jù)庫。除非是這多個數(shù)據(jù)庫。存儲的是相同類型的數(shù)據(jù)(數(shù)據(jù)分片存儲),如由于用戶信息太多而存儲在多個數(shù)據(jù)庫中,不然XA事務(wù)的應(yīng)用場景其實(shí)不多。
分布式事務(wù)方法:Seata框架
?接下來是Seata分布式事務(wù)框架,Seata的大致工作原理如圖所示(工作模式實(shí)際上有4種,不同模式有所區(qū)別)。Seata需要額外部署事務(wù)協(xié)調(diào)服務(wù)(TC)作為全局監(jiān)控的中間件,后端程序需要嵌入Seata的事務(wù)管理器(TM)、資源管理器(RM)等代碼。各個后端程序向事務(wù)協(xié)調(diào)服務(wù)報告其執(zhí)行的結(jié)果,并根據(jù)全局事務(wù)的結(jié)果決定是否回滾已經(jīng)操作成功的數(shù)據(jù)。
由于我們沒有在實(shí)際項目中應(yīng)用過這個框架,就不做過多解釋了。沒有使用的理由并不是它不優(yōu)秀,之前有個項目也是決定使用的,但是最終沒用是因?yàn)榇蠖鄶?shù)工程師沒弄懂(囧)。
對于這種技術(shù)團(tuán)隊理解上存在門檻的技術(shù),我們一直是慎用的,而且也推動我們設(shè)計出了一種更加簡單有效流程方式。
分布式事務(wù)方法:流程方式
我們常用的分布式事務(wù)方法其實(shí)是一種流程的思維。因?yàn)樵趯?shí)際項目當(dāng)中,分布式的事務(wù)的做法需要符合實(shí)際業(yè)務(wù)流程,而不能簡單粗暴地有一條數(shù)據(jù)操作不成功就全局回滾。
比如訂單與庫存的分布式事務(wù),當(dāng)訂單正常生成后,但庫存不足(數(shù)據(jù)操作失敗)。一般情況下,并不要求訂單回滾(用戶會很奇怪),而是應(yīng)該把訂單關(guān)閉,并記錄庫存異常,且通知采購。
其實(shí)大多數(shù)的分布式事務(wù)場景都是一種流程,所以我們做了一個流程中心(以后會開源)。流程中心的數(shù)據(jù)庫記錄了各個流程(包含各異常流程),其他后端程序與流程中心之間通過API調(diào)用。由于調(diào)度中心是獨(dú)立子系統(tǒng),所以即使某個業(yè)務(wù)子系統(tǒng)宕機(jī),也能記錄異常,以方便運(yùn)營管理員通知運(yùn)維人員修復(fù)。
這種流程中心的做法不僅能解決大多數(shù)分布式事務(wù)場景,而且能切斷子系統(tǒng)與子系統(tǒng)的直接聯(lián)系。通過流程中心作為調(diào)度中心,既能保證各子系統(tǒng)的獨(dú)立性,也能對一些復(fù)雜流程進(jìn)行統(tǒng)一管理。而不會出現(xiàn)子系統(tǒng)間有縷不清的關(guān)系。
當(dāng)然,這種流程的方式有一種場景是不合適的。就是同類數(shù)據(jù)分庫分區(qū)記錄的場景(數(shù)據(jù)分片存儲),如兩個用戶記錄在不同區(qū)域的不同數(shù)據(jù)庫,A用戶向B用戶轉(zhuǎn)賬。對于這種場景,還是XA事務(wù)或者使用Seata框架比較合適。
總結(jié)
數(shù)據(jù)庫事務(wù)或者分布式事務(wù),都只是在防止一些極端情況和某些未發(fā)現(xiàn)的bug。很多時候,發(fā)生的概率很低,且在測試階段很難發(fā)現(xiàn)。
但是,這是系統(tǒng)健壯性的保險機(jī)制。如果開發(fā)時不注意事務(wù)的添加,只會徒增運(yùn)營成本(很多投訴),且給用戶留下各種不穩(wěn)定的壞印象。
?
?
?
總結(jié)
以上是生活随笔為你收集整理的【网站架构】一招搞定90%的分布式事务,实打实介绍数据库事务、分布式事务的工作原理应用场景的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决 此 Flash Player 与您
- 下一篇: SQL Server错误代码大全及解释(