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