亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring中如何實現分布式事務

發布時間:2021-08-09 11:55:44 來源:億速云 閱讀:308 作者:Leah 欄目:大數據

本篇文章給大家分享的是有關Spring中如何實現分布式事務,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

分布式系統的實現原則

那么在分布式系統當中,我們應該怎么樣去實現事務呢?這就需要從分布式系統的原則說起。分布式系統的實現原則有幾種說法,如BASE原理、ACP原理。
其中ACP是:

  • A: 可用性(Availability)

  • C: 一致性(Consistency)

  • P: 分區容錯性(Tolerance of network Partition)

A和P沒什么好說的,就是分布式系統的基本特性,C(一致性)就是指在分布式系統當中,多個節點之間數據的一致性,包括一個節點修改的數據,通過另一個節點訪問的時候也能看到;以及當一個操作需要修改多個數據源的數據的時候,多個修改要都能夠完成,或者都不完成。

這里的一致性,我們可以看做是上面說的數據庫事務的ACID特性中,原子性、一致性,甚至是隔離性的統一。如果以ACID這4個特性為要求來實現分布式系統,在現實當中是不可能的,其中原子性就沒有辦法實現。如果一個業務請求,要修改多個數據庫中的數據,那么這多個數據庫的操作,就無法實現原子性,勢必會有一個先后,在第一個數據庫上完成以后,再在第二個數據庫上完成,那么這期間的一點點時間,就違反了原子性。

所以,我們往往無法在分布式系統中實現完全的一致性,所以就有了BASE理論。BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫。BASE理論是對CAP中一致性和可用性權衡的結果,要求實現最終一致性即可。

其中,Soft state(軟狀態)是指,在一個業務操作過程中,允許出現一個中間狀態,也就是軟狀態,而不要求原子性那樣,要么都完成,要么都不完成。例如在下單的時候,出現一個“正在處理”的狀態。由于有這個軟狀態,那我的一致性,就不要求是強一致性,而是最終一致性,也就是說,只要最終這個請求能處理完,所有的數據狀態都是處理完的狀態;如果期間出錯了,所有的數據也都一致,該失敗的失敗、該退錢的退錢、該重置的重置。

分布式事務的實現

所以,確定了分布式系統的實現原則是最終一致性以后,同時也明確了我們實現分布式事務的原則,也是最終一致性。
其實,不管是數據庫事務的ACID特性,還是分布式事務的最終一致性,其實,都是根據事務的定義和它的兩個目標,所采取的不同的實現方式。

那么我們應該怎么實現這個最終一致性呢?

單服務的分布式事務

首先,任何一個分布式系統,總是由一個個的系統組成,也就是一個個的服務,這些服務又可以部署多個。同時,我們的整個系統也需要一定的方式相互作用、相關通信。有時候,我們可以讓一個服務直接調用另一個服務的接口(如果有提供的話);還有時候,我們可以讓兩個服務通過一個MQ之類的消息中間件通信,共同完成一些業務。但是,無論如何,大部分情況下,分布式系統的一個服務總是會訪問多個數據源。最典型的例子就是通過MQ接受一個事件,然后出發一些操作,再把結果發送到另一個隊列里。

對于這種每個服務訪問多個數據源的情況,其實就是一個最簡單的分布式事務的場景。如果大家在網上搜“Spring分布式事務實現”,搜到的結果也都是在說這個場景下的分布式事務實現過程。

要實現這個事務,首先需要對Spring的事物機制有一定了解。對于這種情況,最簡單的就是使用Spring的JTA事務管理。但是,我們知道,JTA事務管理是通過兩階段提交實現的,在很多情況下,它的效率是很低的。因為它在多個數據源修改數據的時候,這些數據一直都處在被鎖的狀態,知道多個數據源的事務都提交完成,才會釋放。

如果不用JTA,Spring也給我們提供了幾種方式,來近似的實現分布式事務(注意這里說的近似)。例如:

  1. 事務同步,也就是提交一個事物的時候,通過Listener等方式通知另一個事務也提交。但是這種情況下,如果第二個事務提交的時候出錯了,第一個事物就無法回滾,因為他已經提交完成了。

  2. 鏈式事務,就是將多個事務,包裝在一個鏈式事務管理器當中,在提交事務的時候,一次提交里面的事務。對于這種實現,也存在上面說的問題。

  3. 還有其他的一些方式,就不過多說明。

所以,使用Spring在單服務多數據源的情況下,實現分布式事務,實際上沒辦法完全實現事務的,因為出錯的時候不能保證都會滾。那么這時候,就需要再通過其他機制來補充。

  1. 首先就是重試,也就是在出錯的時候,重試之前的操作。這在有MQ的時候比較常用,因為一般的MQ服務器,在你讀消息以后,處理的時候如果出錯了,那么這個讀消息的操作不會被提交。那這個消息就會被重新讀到,重新出發剛才的操作。這時候,我們就需要考慮這個方法的冪等性,保證在重復消息的時候不會重復處理數據。

  2. 其次,我們需要自己處理一些錯誤。例如上面的情況,重試幾次以后,一直沒有成功,那么這時候就需要走失敗邏輯。有時候,我們也可以通過一個定時器來檢查一定時間內沒有完成的失敗操作。

  3. 有些情況下,我們還需要考慮其他各種錯誤,如網絡錯誤、超時,系統宕機等等。

大家可以試想一下,分布式系統越復雜,它的各種出錯的情況就越多,我們需要考慮的補救措施就越多。那這種修修補補的實現分布式事務的最終一致性的做法,始終不是一個好的辦法。但是,使用Spring解決單服務的分布式系統,始終是分布式事務實現的基礎。我們可以用其他的模式來方便我們解決分布式事務,但是在每個服務當中,我們還是要經常使用事務同步、鏈式事務等,來實現事務。我們用Spring來保證絕大多數情況下的事務問題,而對于特殊的錯誤情況,就采用其他的模式來解決。

分布式事務實現的模式

剛才說了我們用其他模式來覺得分布式事務問題,那么都有什么模式呢?

消息驅動(Event Driven)模式

消息驅動模式是,當某個業務請求需要由多個服務參與完成的時候,這些服務之前不直接通信,而是通過一個MQ中間件來通信。比如對于一個訂單支付的請求,接收到支付完成的請求后,通過MQ,通知訂單服務去完成訂單,訂單服務再去通知商品服務去減庫存,再通知物流服務去發起物流流程。

那么,對于每一個服務來說,都需要先從一個隊列讀取一個消息,完成自己的業務操作,再往另一個隊列發送一個消息,這就需要操作一個數據和一個MQ服務器。這也就是上面說的單服務的分布式事務實現。對于這種模式而言,我們用事務同步保證在每個服務中,在大部分情況下都能保證事務。即使偶爾出現網絡錯誤、系統錯誤等,通過重試就能解決大部分問題。如果重試一直不能解決,那就再處理失敗邏輯。

我們使用這種方式,最重要的,就是對這個消息、和他的處理流程的編排,其次,它也是一種響應式的編程思維。

事件溯源(Event Sourcing)模式

Event Sourcing在上面說的消息驅動的基礎上,進一步提升事件(也就是之前的消息)的地位,讓它成為系統的一等公民。也就是說,怎么的系統不是基于原先那些實體的,而是基于事件的,一個事件就代表一個業務操作和業務數據狀態的更改。至于業務數據,我們不需要把它保存在數據庫中,即使保存,也只是為了查詢數據方便而保存。

在Event Sourcing模式中,每個服務完成某個邏輯的方式,跟上面說的消息驅動模式差不多,就是對于用戶的每個操作,會產生一個事件(可能多個),這個事件會被某個服務的某個處理方法處理,它也有可能再產生其他的事件,再由其他服務處理,直到完成整個業務流程。但是,它跟消息驅動的最大區別就是,在Event Sourcing的服務里,業務狀態數據不一定要保存在數據庫中,就算保存,出錯了也沒關系,反正它可以根據Event事件重新生成。所以這個地方的事務,我們只需要保證Event保存成功即可。當然,我們需要其他的機制,方便我們能夠重新生成業務數據,而這,一般都是實現Event Sourcing的框架來提供。

TCC(Try-Confirm-Cancel)模式

除了上面說的通過一個中間價關聯不同的服務,在有些分布式系統當中,我們的不同的服務可以直接通信,例如Spring Cloud微服務框架就提供Rest方式訪問別的服務。那么這時候,就相當于,我的一個服務除了訪問自己的數據庫以外,還要訪問別的服務,這里的這個服務就可以當做是一個數據庫。我們可能要調用別的服務的某個接口完成一些業務。

在這種情況下,一個服務提供的接口,不可能實現事務,也就是先操作數據,再Commit,如果出錯了再Rollback。但是,我們可以借鑒事務的這種處理思路,來自己提供類似事務的方法,這就是TCC模式。一個事物是通過Do-Commit/Rollback來實現的,在TCC模式中,是通過給每一個服務間調用的操作接口,提供一套Try-Confirm/Cancel接口。

還是舉一個例子,就是用戶下單以后支付完成。支付完成的時候由先訂單服務處理,然后調用商品服務去減庫存。大家用Spring Cloud的話,可能就在商品服務里寫一個接口直接做減庫存的操作,但是在TCC模式下,我們需要3個接口。首先是減庫存的Try接口,在這里,我們要檢查業務數據的狀態、檢查商品庫存夠不夠,然后做資源的預留,也就是在某個字段上設置預留的狀態。然后在Confirm接口里,完成庫存減1的操作。在Cancel接口里,把之前預留的字段重置。

這可能聽著有點繁瑣,感覺可以一次完成的事情,為什么要分成2步,首先這么做是為了能夠在出錯的時候正確的重置庫存數據,其次這個預留操作跟Confirm操作是兩個請求,中間可能會有其他并發請求。從理論上說,只要我們在Try接口里面預留資源的邏輯是正確的,那么,即使Confirm的時候出錯了,我也可以通過重試Confirm請求來完成

使用數據庫保存事務狀態

這其實不是一種模式,只是一種方式。例如在TCC模式下,在準備調用Confirm接口的時候,目標服務突然宕機了,或者發起請求的服務突然宕機或出錯了,導致這個Confirm請求一直沒有被調用。那么,在系統恢復以后,我該怎么完成之前的事務呢?除了上面說的用定時器定期檢查未完成的操作以外(需要能夠通過某種數據狀態判斷業務沒有執行完成后),我們還可以用數據庫來記錄事務的運行狀態。

例如在TCC模式中,每當一個服務A要使用TCC模式調用另一個服務B的時候,服務A將這個TCC的事務狀態寫到數據庫中,根據具體實現,可能是在調用前記錄當前事務的狀態,調用完成再保存該調用的參數和結果狀態,這個事務完成以后(也就是調用完Confirm,或Cancel以后),再更新成完成的狀態。那么,通過合理的設計,我們就能在各種出錯情況下,保證能繼續完成這個事務,或取消這個事務。

以上就是Spring中如何實現分布式事務,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

砀山县| 孝感市| 湄潭县| 衡阳市| 镇康县| 石城县| 东海县| 吴桥县| 城口县| 化德县| 汉中市| 开化县| 黔西县| 库伦旗| 松滋市| 山阴县| 武宁县| 扎囊县| 甘德县| 穆棱市| 江都市| 东阳市| 仙居县| 祁门县| 福安市| 灌南县| 衢州市| 元氏县| 武邑县| 岐山县| 田东县| 宁都县| 东港市| 石柱| 东方市| 芮城县| 永年县| 遵义县| 福安市| 织金县| 新巴尔虎左旗|