日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

分布式事务六种解决方案

發(fā)布時(shí)間:2024/4/13 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分布式事务六种解决方案 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

常見的分布式事務(wù)包括 2PC、3PC、TCC、本地消息表、消息事務(wù)、最大努力通知。

事務(wù)

嚴(yán)格意義上的事務(wù)實(shí)現(xiàn)應(yīng)該是具備原子性、一致性、隔離性和持久性,簡稱 ACID。

  • 原子性(Atomicity),可以理解為一個(gè)事務(wù)內(nèi)的所有操作要么都執(zhí)行,要么都不執(zhí)行。
  • 一致性(Consistency),可以理解為數(shù)據(jù)是滿足完整性約束的,也就是不會(huì)存在中間狀態(tài)的數(shù)據(jù),比如你賬上有400,我賬上有100,你給我打200塊,此時(shí)你賬上的錢應(yīng)該是200,我賬上的錢應(yīng)該是300,不會(huì)存在我賬上錢加了,你賬上錢沒扣的中間狀態(tài)。
  • 隔離性(Isolation),指的是多個(gè)事務(wù)并發(fā)執(zhí)行的時(shí)候不會(huì)互相干擾,即一個(gè)事務(wù)內(nèi)部的數(shù)據(jù)對(duì)于其他事務(wù)來說是隔離的。
  • 持久性(Durability),指的是一個(gè)事務(wù)完成了之后數(shù)據(jù)就被永遠(yuǎn)保存下來,之后的其他操作或故障都不會(huì)對(duì)事務(wù)的結(jié)果產(chǎn)生影響。

而通俗意義上事務(wù)就是為了使得一些更新操作要么都成功,要么都失敗。

說到這里可能有人會(huì)說,不對(duì)啊 Redis 的事務(wù)不能保證所有操作要么都執(zhí)行要么都不執(zhí)行,為什么它也叫事務(wù)啊?

首先你要知曉一般的中間件都會(huì)夸大其效果,人家團(tuán)隊(duì)也是想更出名,吸引更多的人來使用他們的產(chǎn)品,所以我們得以辯證的角度來看待。

一般而言他們既然敢說出他們實(shí)現(xiàn)了什么什么,要么是真的實(shí)現(xiàn)了,要么是在某種特殊、定制或者極端的條件下才能滿足功能。

我們來看看 Redis 怎么說的。

這句話就是告訴大家事務(wù)中的某個(gè)命令失敗了,之后的命令還是會(huì)被處理,Redis 不會(huì)停止命令,意味著也不會(huì)回滾。

你說這不是扯嘛?這都偏離事務(wù)最核心的本意了啊。

別急,咱們來看看 Redis 怎么解釋的。

?

Redis 官網(wǎng)解釋了為什么不支持回滾,他們說首先如果命令出錯(cuò)那都是語法使用錯(cuò)誤,是你們自己編程出錯(cuò),而且這種情況應(yīng)該在開發(fā)的時(shí)候就被檢測(cè)出來,不應(yīng)在生產(chǎn)環(huán)境中出現(xiàn)。

然后 Redis 就是為了快!不需要提供回滾。

下面還有一段話我就不截圖了,就是說就算提供回滾也沒用,你這代碼都寫錯(cuò)了,回滾并不能使你免于編程錯(cuò)誤。而且一般這種錯(cuò)也不可能進(jìn)入到生產(chǎn)環(huán)境,所以選擇更加簡單、快速的方法,我們不支持回滾。

你看看這說的好像很有道理,我們不提供回滾,因?yàn)槲覀儾恍枰獮槟愕木幊体e(cuò)誤買單!

但好像哪里不對(duì)勁?角度、立場(chǎng)不同,大家自己品。

分布式事務(wù)

分布式事務(wù)顧名思義就是要在分布式系統(tǒng)中實(shí)現(xiàn)事務(wù),它其實(shí)是由多個(gè)本地事務(wù)組合而成。

對(duì)于分布式事務(wù)而言幾乎滿足不了 ACID,其實(shí)對(duì)于單機(jī)事務(wù)而言大部分情況下也沒有滿足 ACID,不然怎么會(huì)有四種隔離級(jí)別呢?所以更別說分布在不同數(shù)據(jù)庫或者不同應(yīng)用上的分布式事務(wù)了。

我們先來看下 2PC。

2PC

2PC(Two-phase commit protocol),中文叫二階段提交。?二階段提交是一種強(qiáng)一致性設(shè)計(jì),2PC 引入一個(gè)事務(wù)協(xié)調(diào)者的角色來協(xié)調(diào)管理各參與者(也可稱之為各本地資源)的提交和回滾,二階段分別指的是準(zhǔn)備(投票)和提交兩個(gè)階段。

注意這只是協(xié)議或者說是理論指導(dǎo),只闡述了大方向,具體落地還是有會(huì)有差異的。

讓我們來看下兩個(gè)階段的具體流程。

準(zhǔn)備階段協(xié)調(diào)者會(huì)給各參與者發(fā)送準(zhǔn)備命令,你可以把準(zhǔn)備命令理解成除了提交事務(wù)之外啥事都做完了。

同步等待所有資源的響應(yīng)之后就進(jìn)入第二階段即提交階段(注意提交階段不一定是提交事務(wù),也可能是回滾事務(wù))。

假如在第一階段所有參與者都返回準(zhǔn)備成功,那么協(xié)調(diào)者則向所有參與者發(fā)送提交事務(wù)命令,然后等待所有事務(wù)都提交成功之后,返回事務(wù)執(zhí)行成功。

假如在第一階段有一個(gè)參與者返回失敗,那么協(xié)調(diào)者就會(huì)向所有參與者發(fā)送回滾事務(wù)的請(qǐng)求,即分布式事務(wù)執(zhí)行失敗。

那可能就有人問了,那第二階段提交失敗的話呢?

這里有兩種情況。

第一種是第二階段執(zhí)行的是回滾事務(wù)操作,那么答案是不斷重試,直到所有參與者都回滾了,不然那些在第一階段準(zhǔn)備成功的參與者會(huì)一直阻塞著。

第二種是第二階段執(zhí)行的是提交事務(wù)操作,那么答案也是不斷重試,因?yàn)橛锌赡芤恍﹨⑴c者的事務(wù)已經(jīng)提交成功了,這個(gè)時(shí)候只有一條路,就是頭鐵往前沖,不斷的重試,直到提交成功,到最后真的不行只能人工介入處理。

3PC

3PC 的出現(xiàn)是為了解決 2PC 的一些問題,相比于 2PC 它在參與者中也引入了超時(shí)機(jī)制,并且新增了一個(gè)階段使得參與者可以利用這一個(gè)階段統(tǒng)一各自的狀態(tài)。

讓我們來詳細(xì)看一下。

3PC 包含了三個(gè)階段,分別是準(zhǔn)備階段、預(yù)提交階段和提交階段,對(duì)應(yīng)的英文就是:CanCommit、PreCommit 和 DoCommit。

看起來是把 2PC 的提交階段變成了預(yù)提交階段和提交階段,但是 3PC 的準(zhǔn)備階段協(xié)調(diào)者只是詢問參與者的自身狀況,比如你現(xiàn)在還好嗎?負(fù)載重不重?這類的。

而預(yù)提交階段就是和 2PC 的準(zhǔn)備階段一樣,除了事務(wù)的提交該做的都做了。

不管哪一個(gè)階段有參與者返回失敗都會(huì)宣布事務(wù)失敗,這和 2PC 是一樣的(當(dāng)然到最后的提交階段和 2PC 一樣只要是提交請(qǐng)求就只能不斷重試)。

TCC

2PC 和 3PC 都是數(shù)據(jù)庫層面的,而 TCC 是業(yè)務(wù)層面的分布式事務(wù),就像我前面說的分布式事務(wù)不僅僅包括數(shù)據(jù)庫的操作,還包括發(fā)送短信等,這時(shí)候 TCC 就派上用場(chǎng)了!

TCC 指的是Try - Confirm - Cancel。

  • Try 指的是預(yù)留,即資源的預(yù)留和鎖定,注意是預(yù)留
  • Confirm 指的是確認(rèn)操作,這一步其實(shí)就是真正的執(zhí)行了。
  • Cancel 指的是撤銷操作,可以理解為把預(yù)留階段的動(dòng)作撤銷了。

其實(shí)從思想上看和 2PC 差不多,都是先試探性的執(zhí)行,如果都可以那就真正的執(zhí)行,如果不行就回滾。

比如說一個(gè)事務(wù)要執(zhí)行A、B、C三個(gè)操作,那么先對(duì)三個(gè)操作執(zhí)行預(yù)留動(dòng)作。如果都預(yù)留成功了那么就執(zhí)行確認(rèn)操作,如果有一個(gè)預(yù)留失敗那就都執(zhí)行撤銷動(dòng)作。

本地消息表

本地消息表其實(shí)就是利用了?各系統(tǒng)本地的事務(wù)來實(shí)現(xiàn)分布式事務(wù)。

本地消息表顧名思義就是會(huì)有一張存放本地消息的表,一般都是放在數(shù)據(jù)庫中,然后在執(zhí)行業(yè)務(wù)的時(shí)候?將業(yè)務(wù)的執(zhí)行和將消息放入消息表中的操作放在同一個(gè)事務(wù)中,這樣就能保證消息放入本地表中業(yè)務(wù)肯定是執(zhí)行成功的。

然后再去調(diào)用下一個(gè)操作,如果下一個(gè)操作調(diào)用成功了好說,消息表的消息狀態(tài)可以直接改成已成功。

如果調(diào)用失敗也沒事,會(huì)有?后臺(tái)任務(wù)定時(shí)去讀取本地消息表,篩選出還未成功的消息再調(diào)用對(duì)應(yīng)的服務(wù),服務(wù)更新成功了再變更消息的狀態(tài)。

這時(shí)候有可能消息對(duì)應(yīng)的操作不成功,因此也需要重試,重試就得保證對(duì)應(yīng)服務(wù)的方法是冪等的,而且一般重試會(huì)有最大次數(shù),超過最大次數(shù)可以記錄下報(bào)警讓人工處理。

可以看到本地消息表其實(shí)實(shí)現(xiàn)的是最終一致性,容忍了數(shù)據(jù)暫時(shí)不一致的情況。

消息事務(wù)

RocketMQ 就很好的支持了消息事務(wù),讓我們來看一下如何通過消息實(shí)現(xiàn)事務(wù)。

第一步先給 Broker 發(fā)送事務(wù)消息即半消息,半消息不是說一半消息,而是這個(gè)消息對(duì)消費(fèi)者來說不可見,然后發(fā)送成功后發(fā)送方再執(zhí)行本地事務(wù)

再根據(jù)本地事務(wù)的結(jié)果向 Broker 發(fā)送 Commit 或者 RollBack 命令。

并且 RocketMQ 的發(fā)送方會(huì)提供一個(gè)反查事務(wù)狀態(tài)接口,如果一段時(shí)間內(nèi)半消息沒有收到任何操作請(qǐng)求,那么 Broker 會(huì)通過反查接口得知發(fā)送方事務(wù)是否執(zhí)行成功,然后執(zhí)行 Commit 或者 RollBack 命令。

如果是 Commit 那么訂閱方就能收到這條消息,然后再做對(duì)應(yīng)的操作,做完了之后再消費(fèi)這條消息即可。

如果是 RollBack 那么訂閱方收不到這條消息,等于事務(wù)就沒執(zhí)行過。

可以看到通過 RocketMQ 還是比較容易實(shí)現(xiàn)的,RocketMQ 提供了事務(wù)消息的功能,我們只需要定義好事務(wù)反查接口即可。

可以看到消息事務(wù)實(shí)現(xiàn)的也是最終一致性。

最大努力通知

其實(shí)我覺得本地消息表也可以算最大努力,事務(wù)消息也可以算最大努力。

就本地消息表來說會(huì)有后臺(tái)任務(wù)定時(shí)去查看未完成的消息,然后去調(diào)用對(duì)應(yīng)的服務(wù),當(dāng)一個(gè)消息多次調(diào)用都失敗的時(shí)候可以記錄下然后引入人工,或者直接舍棄。這其實(shí)算是最大努力了。

事務(wù)消息也是一樣,當(dāng)半消息被commit了之后確實(shí)就是普通消息了,如果訂閱者一直不消費(fèi)或者消費(fèi)不了則會(huì)一直重試,到最后進(jìn)入死信隊(duì)列。其實(shí)這也算最大努力。

所以最大努力通知其實(shí)只是表明了一種柔性事務(wù)的思想:我已經(jīng)盡力我最大的努力想達(dá)成事務(wù)的最終一致了。

適用于對(duì)時(shí)間不敏感的業(yè)務(wù),例如短信通知。

總結(jié)

可以看出 2PC 和 3PC 是一種強(qiáng)一致性事務(wù),不過還是有數(shù)據(jù)不一致,阻塞等風(fēng)險(xiǎn),而且只能用在數(shù)據(jù)庫層面。

而 TCC 是一種補(bǔ)償性事務(wù)思想,適用的范圍更廣,在業(yè)務(wù)層面實(shí)現(xiàn),因此對(duì)業(yè)務(wù)的侵入性較大,每一個(gè)操作都需要實(shí)現(xiàn)對(duì)應(yīng)的三個(gè)方法。

本地消息、事務(wù)消息和最大努力通知其實(shí)都是最終一致性事務(wù),因此適用于一些對(duì)時(shí)間不敏感的業(yè)務(wù)。

?

總結(jié)

以上是生活随笔為你收集整理的分布式事务六种解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。