1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        我還不懂什么是分布式事務(wù)

        共 5344字,需瀏覽 11分鐘

         ·

        2021-03-31 12:14

        老大:來,你搞一搞分布式事務(wù)吧

        我:......,啥是事務(wù)?

        我:先從理論學(xué)起吧

        我不懂什么是事務(wù)

        如果事務(wù)都不懂,就更不用說分布式事務(wù)了,于是我馬上開始學(xué)習(xí)了。

        事務(wù)是應(yīng)用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。

        事務(wù)應(yīng)該具有 4 個屬性:原子性、一致性、隔離性、持久性。這四個屬性通常稱為 ACID 特性。

        換成比較容易理解的話就是,就是一組操作比如增刪改查四個操作要么都成功,要么都失敗,不存結(jié)果不一致的狀態(tài)。

        我不懂什么是分布式事務(wù)

        終于弄明白什么是事務(wù)了,又來了分布式事務(wù)。為什么需要分布式事務(wù)呢?

        事務(wù)更多指的是單機版、單數(shù)據(jù)庫的概念。分布式事務(wù) 指事務(wù)的參與者、支持事務(wù)的服務(wù)器、資源服務(wù)器以及事務(wù)管理器分別位于不同的分布式系統(tǒng)的不同節(jié)點之上 。

        換成比較容易理解的話,就是多個事務(wù)之間再保持事務(wù)的特性,也就是多個事務(wù)之間保證結(jié)果的一致性。

        XA規(guī)范

        有了分布式事務(wù)的場景,就會有解決該問題的方式規(guī)范,XA規(guī)范就是解決分布式事務(wù)的規(guī)范,具體描述見維基百科解釋:

        XA規(guī)范提供了一種重要思想:

        1、引入全局事務(wù)的控制節(jié)點,事務(wù)的協(xié)調(diào)者

        2、多個本地事務(wù)劃分多階段提交(也就是下面講的2PC,3PC)

        我不懂分布式方案

        有了規(guī)范就會有落地方案,下面介紹基于XA規(guī)范的幾個實現(xiàn)協(xié)議。

        首先介紹兩階段提交( Two-phase Commit )和三階段提交( Three-phase Commit )

        2PC( Two-phase Commit )

        兩階段提交,顧名思義就是要分兩步提交。

        這里第一階段稱為準備或者投票階段。引入一個負責協(xié)調(diào)各個本地資源管理器的事務(wù)管理器,

        本地資源管理器一般是由數(shù)據(jù)庫實現(xiàn),事務(wù)管理器在第一階段的時候詢問各個資源管理器是否都就緒,并執(zhí)行完除提交事務(wù)外所有事情,然后把結(jié)果返回給事務(wù)協(xié)調(diào)者。

        如果收到每個資源的回復(fù)都是 成功,則在第二階段提交事務(wù),如果其中任意一個資源的回復(fù)是 失敗, 則回滾事務(wù)。

        這里的實現(xiàn)方式和我們平常開黑玩游戲時差不多,當我們組隊時,隊長會讓大家準備,讓隊員上完廁所吃飽飯,如果所有隊員都準備好,那就開始游戲,如果有任一一個隊員沒有吃飽,沒有確認準備好,就不會開始游戲。

        但是這種協(xié)議也會存在一些問題,如下:

        同步阻塞,這是2PC最大的問題, 嚴格的2PC執(zhí)行過程中,所有參與節(jié)點都是事務(wù)阻塞型的。當參與者占有公共資源時,其他第三方節(jié)點訪問公共資源不得不處于阻塞狀態(tài)

        解決方案:引入引入超時機制,如果長時間沒有收到響應(yīng),執(zhí)行特定的動作。

        協(xié)調(diào)者單點故障,協(xié)調(diào)者在2PC中是最重要的角色,同時也意味著如果他出問題,整個過程就GG了

        解決方案:單點故障的常規(guī)方案就引入副本然后當主節(jié)點掛掉后,重新選主,就像組隊游戲中,如果隊員都準備好后,隊長長時間蹲廁所不開始游戲,游戲程序一般就會踢掉隊長,其他組員切換成隊長身份。

        數(shù)據(jù)不一致,雖然解決了上面幾個問題,但是由于分布式系統(tǒng)存在很多網(wǎng)絡(luò)抖動和調(diào)用失敗場景還是會有數(shù)據(jù)不一致的情況,下面分為協(xié)調(diào)者、參與者、網(wǎng)絡(luò)等故障來詳細分析一下:

        1、協(xié)調(diào)者發(fā)送準備命令前掛掉

        這種相當于事務(wù)直接沒有開始,沒有啥太大影響

        2、協(xié)調(diào)者發(fā)送準備命令后掛掉

        這種情況,如果參與者沒有超時機制,就會造成資源鎖定

        3、協(xié)調(diào)者發(fā)送提交命令前掛掉

        這種情況和上一種情況類似,也會造成資源鎖定

        4、協(xié)調(diào)者發(fā)送提交命令后掛掉

        這種情況很可能是能夠成功執(zhí)行分布式事務(wù)的,因為已經(jīng)到了提交階段說明其他參與者都已經(jīng)準備好,如果失敗就不斷重試

        5、協(xié)調(diào)者發(fā)送回滾命令前掛掉

        這種情況和2、3是類似的,由于參與者收不到執(zhí)行操作的命令,如果沒有超時會一直阻塞并占據(jù)著資源

        6、協(xié)調(diào)者發(fā)送回滾命令后掛掉

        這種情況和4差不多,也是很大概率是能夠成功執(zhí)行回滾事務(wù)的,如果沒有成功,由于已經(jīng)形成了決議,所以只能不斷重試

        7、協(xié)調(diào)者發(fā)送準備命令后,部分參與者掛掉

        這種情況協(xié)調(diào)者有超時機制,直接判定成失敗,然后通知所有參與者回滾

        8、協(xié)調(diào)者發(fā)送準備命令后掛掉,且部分參與者掛掉

        這種情況重新選舉協(xié)調(diào)者后,發(fā)現(xiàn)還在第一階段,由于沒有收到掛掉參與者的響應(yīng),所以判定失敗,通知其他參與者執(zhí)行回滾

        9、協(xié)調(diào)者發(fā)送提交或回滾命令后掛掉,且收到消息的參與者掛掉

        這種情況重新選舉協(xié)調(diào)者后,沒有收到消息的參與者沒有執(zhí)行事務(wù),但是協(xié)調(diào)者無法確定收到消息的參與者執(zhí)行第二階段的提交或回滾到底是否成功,就會出現(xiàn)事務(wù)不一致的情況

        3PC( Three-phase Commit )

        從上面介紹的相關(guān)內(nèi)容也可以大體知道2PC的缺點和解決方式,于是就有了下面的解決協(xié)議,三階段提交

        從百科可以看到3PC的引入主要就是為了解決上面我們說的2PC的缺點,咋就能解決呢?

        1、3PC是非阻塞協(xié)議

        好的,就是為了解決了資源占用問題,主要也就是引入了參與者超時機制

        2、 第一階段與第二階段之間插入了一個準備階段

        解決了在兩階段提交中,參與者在投票之后,由于協(xié)調(diào)者發(fā)生崩潰或錯誤,而導(dǎo)致參與者處于無法知曉是否提交或者回滾的“不確定狀態(tài)”,也就是為了保證最后提交階段之前所有參與節(jié)點狀態(tài)一致

        3PC 把2PC第一階段再次拆分為2個階段,多了一個階段其實就是在執(zhí)行事務(wù)之前來確認參與者是否正常,防止個別參與者不正常的情況下,其他參與者都執(zhí)行了事務(wù)鎖定資源。

        他的大概步驟其實可以按照參與者4個狀態(tài)來劃分

        0、初始狀態(tài),此階段事務(wù)發(fā)起者觸發(fā)全局事務(wù),參與者切換本地狀態(tài)為開始狀態(tài),并把自己注冊到協(xié)調(diào)者中。

        1、可提交或狀態(tài)等待,此階段協(xié)調(diào)者發(fā)送命令到每個注冊過來的參與者,讓他們更改狀態(tài)為可提交狀態(tài)。

        2、預(yù)提交狀態(tài),此階段協(xié)調(diào)者收到參與者確認可以提交并進入狀態(tài),然后協(xié)調(diào)者向他們發(fā)送預(yù)提交消息,參與者鎖定資源,并更改狀態(tài)為預(yù)提交狀態(tài)。同時 協(xié)調(diào)者也進入預(yù)提交狀態(tài)。

        3、提交狀態(tài),此階段協(xié)調(diào)者根據(jù)參與者預(yù)提交的結(jié)果執(zhí)行提交或回滾操作,然后釋放資源。

        通過這種方式可以解決一些2PC狀態(tài)不一致問題。JBoss上大佬的總結(jié):

        大概意思是,通過引入預(yù)提交階段,協(xié)調(diào)者能夠確定參與者提交前的狀態(tài),同時參與者也能夠推斷其他參與者狀態(tài)

        協(xié)調(diào)者正常的情況下,可以根據(jù)參與者狀態(tài)切換的結(jié)果來決定是執(zhí)行還是回滾。多出的一個預(yù)提交階段就是為了統(tǒng)一狀態(tài)。

        參與者如果沒有收到協(xié)調(diào)者消息,會默認執(zhí)行提交,雖然可能會導(dǎo)致數(shù)據(jù)不一致。

        協(xié)調(diào)者掛掉重新選舉后,會根據(jù)參與者和原主節(jié)點狀態(tài)確定是執(zhí)行還是回滾。

        新協(xié)調(diào)者來的時候發(fā)現(xiàn)自己是可提交狀態(tài)并且參與者為可提交和回滾狀態(tài),說明經(jīng)過投票回滾的,此時新協(xié)調(diào)者執(zhí)行回滾命令

        新協(xié)調(diào)者來的時候發(fā)現(xiàn)自己是預(yù)提交并且參與者處于預(yù)提交和提交狀態(tài),那么表明已經(jīng)經(jīng)過了所有參與者的確認了,所以此時執(zhí)行的就是提交命令

        可以看到3PC由于多引入了一個階段,性能會比較低,而且其實也沒有解決數(shù)據(jù)一致性問題,多了一個階段的效果也不能保證效果一定要比2PC要好,所以一般還是很少用。

        TCC(Try-Confirm-Cancel)

        2PC/3PC 模式基于 支持本地 ACID 事務(wù)關(guān)系型數(shù)據(jù)庫

        • 一階段 prepare 行為:在本地事務(wù)中,一并提交業(yè)務(wù)數(shù)據(jù)更新和相應(yīng)回滾日志記錄。
        • 二階段 commit 行為:馬上成功結(jié)束,自動 異步批量清理回滾日志。
        • 二階段 rollback 行為:通過回滾日志,自動 生成補償操作,完成數(shù)據(jù)回滾。

        相應(yīng)的,TCC 模式從業(yè)務(wù)層面處理,不依賴于底層數(shù)據(jù)資源的事務(wù)支持:

        • 一階段 prepare 行為:調(diào)用 自定義 的 prepare 邏輯。
        • 二階段 commit 行為:調(diào)用 自定義 的 commit 邏輯。
        • 二階段 rollback 行為:調(diào)用 自定義 的 rollback 邏輯。

        所謂 TCC 模式,是指支持把 自定義 的分支事務(wù)納入到全局事務(wù)的管理中,可以不依賴本地數(shù)據(jù)庫,當然實現(xiàn)上可以依賴,更多的場景還是兩者結(jié)合。

        TCC更多的是讓業(yè)務(wù)來實現(xiàn)兩階段提交的思想,對業(yè)務(wù)侵入性大

        Try階段定義為執(zhí)行資源的鎖定,這個階段我認為比較難實現(xiàn),常規(guī)的思路是

        轉(zhuǎn)賬場景時可能需要把嘗試賬戶余額是否足夠,然后減去轉(zhuǎn)賬金額并把金額存入到臨時字段,做到鎖定金額

        緩存場景可能就需要使用分布式鎖,鎖定住要操作的緩存值,或者取出某個緩存到另一個緩存

        上傳下載場景可能需要把文件存到服務(wù)器臨時目錄

        Confirm階段定義為執(zhí)行try階段鎖定的資源,也就是說基于try的成功,可以繼續(xù)操作,比如執(zhí)行真正的轉(zhuǎn)賬、緩存操作、上傳下載等。

        Cancel階段定義為釋放Try預(yù)留的資源,也就是說由于Try的失敗,需要作出相應(yīng)的補償操作或者恢復(fù)環(huán)境,比如刪除掉轉(zhuǎn)賬時的臨時字段、釋放掉鎖、清理臨時文件等。

        TCC模式實現(xiàn)難度還是蠻大的,需要考慮很多異常場景,還要考慮資源如何鎖定和釋放,但是由于不會阻塞資源,應(yīng)用方面也更廣,據(jù)說還是有很多公司熱衷于這種補償型的事務(wù)實現(xiàn)方式

        還有就是這里所說的TCC更多是一種思想,實際實現(xiàn)可能還是需要根據(jù)具體業(yè)務(wù)來做相應(yīng)的調(diào)整,方法是死的,人是活的。

        SAGA

        理論基礎(chǔ)(點擊查看原論文):Hector & Kenneth 發(fā)表論文Sagas (1987)

        Saga模式提供的是長事務(wù)解決方案,在Saga模式中,業(yè)務(wù)流程中每個參與者都提交本地事務(wù),當出現(xiàn)某一個參與者失敗則補償前面已經(jīng)成功的參與者,一階段正向服務(wù)和二階段補償服務(wù)都由業(yè)務(wù)開發(fā)實現(xiàn)。

        適用場景:

        • 業(yè)務(wù)流程長、業(yè)務(wù)流程多
        • 參與者包含其它公司或遺留系統(tǒng)服務(wù),無法提供 TCC 模式要求的三個接口

        Saga主要思想是依賴于狀態(tài)機轉(zhuǎn)換,長事務(wù)拆分成多個短事務(wù),依次執(zhí)行短事務(wù)

        如果某個短事務(wù)失敗,則按照前面執(zhí)行順序的逆序執(zhí)行補償事務(wù)

        這種模式還少使用的,實現(xiàn)也是比較復(fù)雜,同時流程很長,當遇到類似場景時還是需要仔細考慮是否有必要去實現(xiàn)分布式事務(wù)呢?

        本地消息表

        執(zhí)行業(yè)務(wù)的時候 將業(yè)務(wù)的執(zhí)行和將消息放入消息表中的操作放在同一個事務(wù)中,這樣就能保證消息放入本地表中業(yè)務(wù)肯定是執(zhí)行成功的。

        然后再去調(diào)用下一個服務(wù),如果成功了,消息表的消息狀態(tài)可以直接改成已成功。

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

        一般也會有重試次數(shù)限制,超出后執(zhí)行回滾或者通知人工介入。

        可見本地消息表也會出現(xiàn)數(shù)據(jù)不一致的情況,盡量保證最終一致性。

        消息隊列

        此方案的意思是通過支持事務(wù)的消息隊列來實現(xiàn)分布式事務(wù)。

        主要流程:

        1. 生產(chǎn)者發(fā)送半事務(wù)消息到MQ
        2. 生產(chǎn)者收到MQ成功接收到之后,去執(zhí)行本地事務(wù),但是事務(wù)還沒有提交。
        3. 生產(chǎn)者會根據(jù)事務(wù)的執(zhí)行結(jié)果來決定發(fā)送提交或者回滾到消息
        4. 生產(chǎn)者需要提供一個查詢事務(wù)狀態(tài)接口,如果一段時間內(nèi)半消息沒有收到任何操作請求,那么 MQ 會通過查詢接口獲得發(fā)送方事務(wù)執(zhí)行結(jié)果。
        5. 如果是失敗結(jié)果的消息,MQ直接丟棄,也就不會影響到消費者
        6. 如果是成功結(jié)果的消息,消費者消費半事務(wù)消息,然后再去消費普通消息

        該方案與本地消息不同點是去掉了本地消息表,本地事務(wù)和MQ事務(wù)綁定在一起。目前市面上實現(xiàn)該方案的應(yīng)該只有阿里的 RocketMq

        最大努力通知

        這種方式請進行最大努力自行學(xué)習(xí)吧

        我不懂怎么實現(xiàn)

        學(xué)了這么多方案,自己實現(xiàn)還是很有難度。

        常見的解決方案的實現(xiàn)框架有:byteTCC 、華為 ServiceComb 實現(xiàn)的DTM(華為cloud官網(wǎng)可見)、阿里seata(收費版為GTS)、騰訊DTF

        目前開源最火的還是seata,支持模式多、官網(wǎng)文檔詳細,這里就不一一介紹了

        關(guān)于seata的文章非常多,下篇文章也打算以seata框架實踐分布式事務(wù)。

        那seata是不是就完美了呢?當然不是,以后可能改進的幾點

        1、不支持控制臺,沒有可視化界面,驗證全靠打印和連接數(shù)據(jù)庫

        2、seata-server高可用不支持Raft協(xié)議,事務(wù)信息完全依賴于DB、redis等

        3、undoLog占用空間過大尤其是前后置鏡像一個大JSON字段,數(shù)據(jù)量大時可能會入庫慢,可能需要進行壓縮

        4、只能通過異?;貪L,不支持類似Spring的Rollback-Only標志位回滾

        5、全局鎖的粒度是不是有點大,分支事務(wù)是否有必要上報狀態(tài)到TC

        找到一份seata開源作者 jimin slievrly 的分享視頻一起學(xué)習(xí)

        如果需要視頻中PPT學(xué)習(xí),公眾號內(nèi)回復(fù)seata即可

        我懂了

        本文按照完全沒接觸過事務(wù)的學(xué)習(xí)流程進行書寫,腦圖如下:

        左邊是基礎(chǔ),右邊是方案,如果你也在學(xué)習(xí)分布式事務(wù)相關(guān)知識,可以參考。

        本文是系列第一篇,后面計劃一篇為seata實戰(zhàn),一篇為seata原理和如何設(shè)計一個通用分布式事務(wù)框架。感謝閱讀,歡迎關(guān)注。

        — 【 THE END 】—
        本公眾號全部博文已整理成一個目錄,請在公眾號里回復(fù)「m」獲??!


        3T技術(shù)資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號內(nèi)回復(fù)「1024」,即可免費獲?。?!





        瀏覽 17
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            看操比| 操逼免费在线观看 | 丁香五月综合久久 | 国产麻豆视频在线观看 | 亚洲AV无码成人精品国产 | 亚洲精品人伦一区二区 | 囯产精品久久久久久久久久青青 | 午夜毛片影院 | 操屄真好| 五月天色综合 |