欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Java實現(xiàn)分布式事務的三種方案

 更新時間:2021年06月11日 17:07:45   作者:村口張大爺  
現(xiàn)在互聯(lián)網(wǎng)下,分布式和微服務橫行,難免會遇到分布式下的事務問題,當然微服務下可能沒有分布式事務,但是很多場景是需要分布式事務的。下面就來介紹下什么是分布式事務和分布式事務的解決方案

一、問題描述

用戶支付完成會將支付狀態(tài)及訂單狀態(tài)保存在訂單數(shù)據(jù)庫中,由訂單服務去維護訂單數(shù)據(jù)庫。由庫存服務去維護庫存數(shù)據(jù)庫的信息。下圖是系統(tǒng)結(jié)構(gòu)圖:

如何實現(xiàn)兩個分布式服務(訂單服務、庫存服務)共同完成一件事即訂單支付成功自動減庫存,這里的關(guān)鍵是如何保證兩個分布式服務的事務的一致性。

嘗試解決上邊的需求,在訂單服務中遠程調(diào)用減庫存接口,偽代碼如下:

訂單支付結(jié)果通知方法{

​ 更新支付表中支付狀態(tài)為“成功”。
​ 遠程調(diào)用減庫存接口減庫存。

上邊的邏輯說明:

1、更新支付表狀態(tài)為本地數(shù)據(jù)庫操作。
2、遠程調(diào)用減庫存接口為網(wǎng)絡遠程調(diào)用請求。
3、為保存事務上邊兩步操作由spring控制事務,當遇到Exception異常則回滾本地數(shù)據(jù)庫操作。

問題如下:

1、如果更新支付表失敗則拋出異常,不再執(zhí)行遠程調(diào)用,此設想沒有問題。
2、如果更新支付表成功,網(wǎng)絡遠程調(diào)用超時會拉長本地數(shù)據(jù)庫事務時間,影響數(shù)據(jù)庫性能。
3、如果更新支付表成功,遠程調(diào)用減庫存成功(減庫存數(shù)據(jù)庫commit成功),最后更新支付表commit失敗,此時出現(xiàn)操作不一致。

上邊的問題涉及到分布式事務控制。

二、分布式事務

2.1、什么是分布式系統(tǒng)

部署在不同結(jié)點上的系統(tǒng)通過網(wǎng)絡交互來完成協(xié)同工作的系統(tǒng)。

比如:充值加積分的業(yè)務,用戶在充值系統(tǒng)向自己的賬戶充錢,在積分系統(tǒng)中自己積分相應的增加。充值系統(tǒng)和積分系統(tǒng)是兩個不同的系統(tǒng),一次充值加積分的業(yè)務就需要這兩個系統(tǒng)協(xié)同工作來完成。

2.2、什么是事務

事務是指由一組操作組成的一個工作單元,這個工作單元具有原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)。

原子性:執(zhí)行單元中的操作要么全部執(zhí)行成功,要么全部失敗。如果有一部分成功一部分失敗那么成功的操作要全部回滾到執(zhí)行前的狀態(tài)。

一致性:執(zhí)行一次事務會使用數(shù)據(jù)從一個正確的狀態(tài)轉(zhuǎn)換到另一個正確的狀態(tài),執(zhí)行前后數(shù)據(jù)都是完整的。

隔離性:在該事務執(zhí)行的過程中,任何數(shù)據(jù)的改變只存在于該事務之中,對外界沒有影響,事務與事務之間是完全的隔離的。只有事務提交后其它事務才可以查詢到最新的數(shù)據(jù)。

持久性:事務完成后對數(shù)據(jù)的改變會永久性的存儲起來,即使發(fā)生斷電宕機數(shù)據(jù)依然在。

2.3、什么是本地事務

本地事務就是用關(guān)系數(shù)據(jù)庫來控制事務,關(guān)系數(shù)據(jù)庫通常都具有ACID特性,傳統(tǒng)的單體應用通常會將數(shù)據(jù)全部存儲在一個數(shù)據(jù)庫中,會借助關(guān)系數(shù)據(jù)庫來完成事務控制。

2.4、什么是分布式事務

在分布式系統(tǒng)中一次操作由多個系統(tǒng)協(xié)同完成,這種一次事務操作涉及多個系統(tǒng)通過網(wǎng)絡協(xié)同完成的過程稱為分布式事務。這里強調(diào)的是多個系統(tǒng)通過網(wǎng)絡協(xié)同完成一個事務的過程,并不強調(diào)多個系統(tǒng)訪問了不同的數(shù)據(jù)庫,即使多個系統(tǒng)訪問的是同一個數(shù)據(jù)庫也是分布式事務,如下圖:

另外一種分布式事務的表現(xiàn)是,一個應用程序使用了多個數(shù)據(jù)源連接了不同的數(shù)據(jù)庫,當一次事務需要操作多個數(shù)據(jù)源,此時也屬于分布式事務,當系統(tǒng)作了數(shù)據(jù)庫拆分后會出現(xiàn)此種情況。

分布式事務有哪些應用場景:

電商系統(tǒng)中的下單扣庫存

電商系統(tǒng)中,訂單系統(tǒng)和庫存系統(tǒng)是兩個系統(tǒng),一次下單的操作由兩個系統(tǒng)協(xié)同完成

2)金融系統(tǒng)中的銀行卡充值
在金融系統(tǒng)中通過銀行卡向平臺充值需要通過銀行系統(tǒng)和金融系統(tǒng)協(xié)同完成。

3)教育系統(tǒng)中下單選課業(yè)務
在線教育系統(tǒng)中,用戶購買課程,下單支付成功后學生選課成功,此事務由訂單系統(tǒng)和選課系統(tǒng)協(xié)同完成。

4) SNS系統(tǒng)的消息發(fā)送
在社交系統(tǒng)中發(fā)送站內(nèi)消息同時發(fā)送手機短信,一次消息發(fā)送由站內(nèi)消息系統(tǒng)和手機通信系統(tǒng)協(xié)同完成。

三、如何進行分布式事務控制

3.1、CAP理論

CAP理論是分布式事務處理的理論基礎:分布式系統(tǒng)在設計時只能在一致性(Consistency)、可用性(Availability)、分區(qū)容忍性(PartitionTolerance)中滿足兩種,無法兼顧三種。

一致性(Consistency):服務A、B、C三個結(jié)點都存儲了用戶數(shù)據(jù), 三個結(jié)點的數(shù)據(jù)需要保持同一時刻數(shù)據(jù)一致性。

可用性(Availability):服務A、B、C三個結(jié)點,其中一個結(jié)點宕機不影響整個集群對外提供服務,如果只有服務A結(jié)點,當服務A宕機整個系統(tǒng)將無法提供服務,增加服務B、C是為了保證系統(tǒng)的可用性。

分區(qū)容忍性(Partition Tolerance):分區(qū)容忍性就是允許系統(tǒng)通過網(wǎng)絡協(xié)同工作,分區(qū)容忍性要解決由于網(wǎng)絡分區(qū)導致數(shù)據(jù)的不完整及無法訪問等問題。

分布式系統(tǒng)不可避免的出現(xiàn)了多個系統(tǒng)通過網(wǎng)絡協(xié)同工作的場景,結(jié)點之間難免會出現(xiàn)網(wǎng)絡中斷、網(wǎng)延延遲等現(xiàn)象,這種現(xiàn)象一旦出現(xiàn)就導致數(shù)據(jù)被分散在不同的結(jié)點上,這就是網(wǎng)絡分區(qū)

3.2、分布式系統(tǒng)如果兼顧CAP

在保證分區(qū)容忍性的前提下一致性和可用性無法兼顧,如果要提高系統(tǒng)的可用性就要增加多個結(jié)點,如果要保證數(shù)據(jù)的一致性就要實現(xiàn)每個結(jié)點的數(shù)據(jù)一致,結(jié)點越多可用性越好,但是數(shù)據(jù)一致性越差。

所以,在進行分布式系統(tǒng)設計時,同時滿足“一致性”、“可用性”和“分區(qū)容忍性”三者是幾乎不可能的。

CAP有哪些組合方式?

1.CA:放棄分區(qū)容忍性,加強一致性和可用性,關(guān)系數(shù)據(jù)庫按照CA進行設計。

2.AP:放棄一致性,加強可用性和分區(qū)容忍性,追求最終一致性,很多NoSQL數(shù)據(jù)庫按照AP進行設計。
說明:這里放棄一致性是指放棄強一致性,強一致性就是寫入成功立刻要查詢出最新數(shù)據(jù)。追求最終一致性是指允許暫時的數(shù)據(jù)不一致,只要最終在用戶接受的時間內(nèi)數(shù)據(jù) 一致即可。

3.CP:放棄可用性,加強一致性和分區(qū)容忍性,一些強一致性要求的系統(tǒng)按CP進行設計,比如跨行轉(zhuǎn)賬,一次轉(zhuǎn)賬請求要等待雙方銀行系統(tǒng)都完成整個事務才算完成。說明:由于網(wǎng)絡問題的存在CP系統(tǒng)可能會出現(xiàn)待等待超時,如果沒有處理超時問題則整理系統(tǒng)會出現(xiàn)阻塞。

總結(jié)

​ 在分布式系統(tǒng)設計中AP的應用較多,即保證分區(qū)容忍性和可用性,犧牲數(shù)據(jù)的強一致性(寫操作后立刻讀取到最新數(shù)據(jù)),保證數(shù)據(jù)最終一致性。比如:訂單退款,今日退款成功,明日賬戶到賬,只要在預定的用戶可以接受的時間內(nèi)退款事務走完即可。

四、分布式事務一致性解決方案

4.1、兩階段提交協(xié)議(2PC)

​ 為解決分布式系統(tǒng)的數(shù)據(jù)一致性問題出現(xiàn)了兩階段提交協(xié)議(2 Phase Commitment Protocol),兩階段提交由協(xié)調(diào)者和參與者組成,共經(jīng)過兩個階段和三個操作,部分關(guān)系數(shù)據(jù)庫如Oracle、MySQL支持兩階段提交協(xié)議,本節(jié)講解關(guān)系數(shù)據(jù)庫兩階段提交協(xié)議。

參考:

2PC:https://en.wikipedia.org/wiki/Two-phase_commit_protocol

2PC協(xié)議流程圖

1)第一階段:準備階段(prepare)
協(xié)調(diào)者通知參與者準備提交訂單,參與者開始投票。
參與者完成準備工作向協(xié)調(diào)者回應Yes|NO。

2)第二階段:提交(commit)/回滾(rollback)階段
協(xié)調(diào)者根據(jù)參與者的投票結(jié)果發(fā)起最終的提交指令。
如果有參與者沒有準備好則發(fā)起回滾指令。

一個下單減庫存的例子:

1、應用程序連接兩個數(shù)據(jù)源。

2、應用程序通過事務協(xié)調(diào)器向兩個庫發(fā)起prepare,兩個數(shù)據(jù)庫收到消息分別執(zhí)行本地事務(記錄日志),但不提交,如果執(zhí)行成功則回復yes,否則回復no。

3、事務協(xié)調(diào)器收到回復,只要有一方回復no則分別向參與者發(fā)起回滾事務,參與者開始回滾事務。

4、事務協(xié)調(diào)器收到回復,全部回復yes,此時向參與者發(fā)起提交事務。如果參與者有一方提交事務失敗則由事務協(xié)調(diào)器發(fā)起回滾事務。

2PC的優(yōu)點:實現(xiàn)強一致性,部分關(guān)系數(shù)據(jù)庫支持(Oracle、MySQL等)。

缺點:整個事務的執(zhí)行需要由協(xié)調(diào)者在多個節(jié)點之間去協(xié)調(diào),增加了事務的執(zhí)行時間,性能低下。

解決方案有:springboot+Atomikos or Bitronix

3PC主要是解決協(xié)調(diào)者與參與者通信阻塞問題而產(chǎn)生的,它比2PC傳遞的消息還要多,性能不高。

詳細參考3PC:

https://en.wikipedia.org/wiki/Three-phase_commit_protocol

4.2、事務補償 TCC

TCC事務補償是基于2PC實現(xiàn)的業(yè)務層事務控制方案,它是Try、Confirm和Cancel三個單詞的首字母,含義如下:

1、Try 檢查及預留業(yè)務資源完成提交事務前的檢查,并預留好資源。
2、Confirm確定執(zhí)行業(yè)務操作對try階段預留的資源正式執(zhí)行。
3、Cancel取消執(zhí)行業(yè)務操作對try階段預留的資源釋放。

下邊用一個下單減庫存的業(yè)務為例來說明:

1、Try

下單業(yè)務由訂單服務和庫存服務協(xié)同完成,在try階段訂單服務和庫存服務完成檢查和預留資源。
訂單服務檢查當前是否滿足提交訂單的條件(比如:當前存在未完成訂單的不允許提交新訂單)。
庫存服務檢查當前是否有充足的庫存,并鎖定資源。

2、Confirm

訂單服務和庫存服務成功完成Try后開始正式執(zhí)行資源操作。
訂單服務向訂單寫一條訂單信息。
庫存服務減去庫存。

3、Cancel

如果訂單服務和庫存服務有一方出現(xiàn)失敗則全部取消操作。
訂單服務需要刪除新增的訂單信息。
庫存服務將減去的庫存再還原。
優(yōu)點:最終保證數(shù)據(jù)的一致性,在業(yè)務層實現(xiàn)事務控制,靈活性好。
缺點:開發(fā)成本高,每個事務操作每個參與者都需要實現(xiàn)try/confirm/cancel三個接口。

注意:TCC的try/confirm/cancel接口都要實現(xiàn)冪等性,在為在try、confirm、cancel失敗后要不斷重試。

什么是冪等性?

冪等性是指同一個操作無論請求多少次,其結(jié)果都相同。
冪等操作實現(xiàn)方式有:

1、操作之前在業(yè)務方法進行判斷如果執(zhí)行過了就不再執(zhí)行。
2、緩存所有請求和處理的結(jié)果,已經(jīng)處理的請求則直接返回結(jié)果。
3、在數(shù)據(jù)庫表中加一個狀態(tài)字段(未處理,已處理),數(shù)據(jù)操作時判斷未處理時再處理。

4.3、消息隊列實現(xiàn)最終一致性

本方案是將分布式事務拆分成多個本地事務來完成,并且由消息隊列異步協(xié)調(diào)完成,如下圖:
下邊以下單減少庫存為例來說明:

可以把MQ去掉不使用MQ

1、訂單服務和庫存服務完成檢查和預留資源。
2、訂單服務在本地事務中完成添加訂單表記錄和添加“減少庫存任務消息”。
3、由定時任務根據(jù)消息表的記錄發(fā)送給MQ通知庫存服務執(zhí)行減庫存操作。
4、庫存服務執(zhí)行減少庫存,并且記錄執(zhí)行消息狀態(tài)(為避免重復執(zhí)行消息,在執(zhí)行減庫存之前查詢是否執(zhí)行過此消息)。
5、庫存服務向MQ發(fā)送完成減少庫存的消息。
6、訂單服務接收到完成庫存減少的消息后刪除原來添加的“減少庫存任務消息”。
實現(xiàn)最終事務一致要求:預留資源成功理論上要求正式執(zhí)行成功,如果執(zhí)行失敗會進行重試,要求業(yè)務執(zhí)行方法實現(xiàn)冪等。

優(yōu)點 :

由MQ按異步的方式協(xié)調(diào)完成事務,性能較高。
不用實現(xiàn)try/confirm/cancel接口,開發(fā)成本比TCC低。

缺點:

此方式基于關(guān)系數(shù)據(jù)庫本地事務來實現(xiàn),會出現(xiàn)頻繁讀寫數(shù)據(jù)庫記錄,浪費數(shù)據(jù)庫資源,另外對于高并發(fā)操作不是最佳方案。

以上就是淺談Java實現(xiàn)分布式事務的三種方案的詳細內(nèi)容,更多關(guān)于Java 分布式事務的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實現(xiàn)八個常用的排序算法:插入排序、冒泡排序、選擇排序、希爾排序等

    Java實現(xiàn)八個常用的排序算法:插入排序、冒泡排序、選擇排序、希爾排序等

    這篇文章主要介紹了Java如何實現(xiàn)八個常用的排序算法:插入排序、冒泡排序、選擇排序、希爾排序 、快速排序、歸并排序、堆排序和LST基數(shù)排序,需要的朋友可以參考下
    2015-07-07
  • java根據(jù)當前時間獲取yyyy-MM-dd?HH:mm:ss標準格式的時間代碼示例

    java根據(jù)當前時間獲取yyyy-MM-dd?HH:mm:ss標準格式的時間代碼示例

    在Java中可以使用java.time包中的LocalDateTime類和DateTimeFormatter類來獲取并格式化當前時間為yyyy-MM-dd?HH:mm:ss的格式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • java通過Arrays.sort(int[] a)實現(xiàn)由大到小排序的方法實現(xiàn)

    java通過Arrays.sort(int[] a)實現(xiàn)由大到小排序的方法實現(xiàn)

    Java中的Arrays.sort()方法是一種內(nèi)置的排序方法,用于對數(shù)組進行排序,本文就來介紹一下java中的Arrays.sort()排序方法的用法,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • Java Stream reduce()使用指南

    Java Stream reduce()使用指南

    reduce()是Java Stream API中的一個重要終端操作,用于將流中的元素通過二元運算符結(jié)合起來,生成單一結(jié)果,它主要用于計算總和、乘積、最大值、最小值和字符串連接等,本文給大家介紹Java Stream reduce(),感興趣的朋友一起看看吧
    2024-10-10
  • Java反射使用的詳細介紹(最新推薦)

    Java反射使用的詳細介紹(最新推薦)

    這篇文章主要介紹了Java反射使用的詳細介紹,反射的第一步都是先得到編譯后的Class類對象,然后就可以得到Class的全部成分,本文結(jié)合實例代碼詳細講解,需要的朋友可以參考下
    2023-02-02
  • Java中channel用法總結(jié)

    Java中channel用法總結(jié)

    這篇文章主要介紹了Java中channel用法,較為詳細的總結(jié)了channel的定義、類型及使用技巧,需要的朋友可以參考下
    2015-06-06
  • SpringBoot對SSL的支持實現(xiàn)

    SpringBoot對SSL的支持實現(xiàn)

    本文主要介紹了SpringBoot對SSL的支持實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-08-08
  • 淺析IDEA如何正確配置Gradle? GRADLE_USER_HOME 和 Gradle user home的區(qū)別

    淺析IDEA如何正確配置Gradle? GRADLE_USER_HOME 和 Gradle user home的區(qū)別

    這篇文章主要介紹了IDEA如何正確配置Gradle? GRADLE_USER_HOME 和 Gradle user home的區(qū)別,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java垃圾回收之標記壓縮算法詳解

    Java垃圾回收之標記壓縮算法詳解

    今天小編就為大家分享一篇關(guān)于Java垃圾回收之標記壓縮算法詳解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Java GZIP壓縮與解壓縮代碼實例

    Java GZIP壓縮與解壓縮代碼實例

    這篇文章主要介紹了Java GZIP壓縮與解壓縮代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01

最新評論