1. 程式人生 > >面試被問分散式事務(2PC、3PC、TCC),這樣解釋沒毛病!

面試被問分散式事務(2PC、3PC、TCC),這樣解釋沒毛病!

> 整理了一些Java方面的架構、面試資料(微服務、叢集、分散式、中介軟體等),有需要的小夥伴可以關注公眾號【程式設計師內點事】,無套路自行領取 更多優選 - [一口氣說出 9種 分散式ID生成方式,面試官有點懵了](https://mp.weixin.qq.com/s?__biz=MzAxNTM4NzAyNg==&mid=2247483785&idx=1&sn=8b828a8ae1701b810fe3969be536cb14&chksm=9b859174acf21862f0b95e0502a1a441c496a5488f5466b2e147d7bb9de072bde37c4db25d7a&token=745402269&lang=zh_CN#rd) - [面試總被問分庫分表怎麼辦?你可以這樣懟他](https://mp.weixin.qq.com/s?__biz=MzAxNTM4NzAyNg==&mid=2247483882&idx=1&sn=9e0901dd19e3e06a135fe96780c43477&chksm=9b859117acf218017d9273d4328258c01f6a105180ae8534dc0aaa362cc0c3020dd55de3a95e&token=361009039&lang=zh_CN#rd) - [3萬字總結,Mysql優化之精髓](https://juejin.im/post/5e3eb616f265da570d734dcb) - [技術部突然宣佈:JAVA開發人員全部要會介面自動化測試框架](https://mp.weixin.qq.com/s?__biz=MzAxNTM4NzAyNg==&mid=2247483790&idx=1&sn=f2cb1cc3a4159f6565799e7cec45c9d7&chksm=9b859173acf218654de6344b576b02cca619dd09b6df4750828315b3d591df82a03055032e0c&token=745402269&lang=zh_CN#rd) - [9種分散式ID生成之美團(Leaf)實戰](https://mp.weixin.qq.com/s?__biz=MzAxNTM4NzAyNg==&mid=2247483889&idx=1&sn=35b0eb32de3e63c013585ef1db5d3076&chksm=9b85910cacf2181a23bdc1344a1984e3fa7613cc8dd9e28f3b10196fc73b9022d735f4031e88&token=662935248&lang=zh_CN#rd) #### 絮絮叨叨 還記得剛入行開始寫Java時,接觸的第一個專案是國家電網的一個業務系統,這個系統據說投資了5億人民幣進行研發,鼎盛時期研發人員一度達到過500人。專案採用當時最流行的ssh(Struts+Spring+Hibernate)框架,典型的三層架構(controller - > service -> dao)簡單又粗暴,所有人寫的程式碼都放在一個大工程裡,專案檔案大小達到幾百M,解決程式碼衝突是當時最大的工作量。 然而戲劇性的是,交測當天五人同時上線,專案崩 崩 崩潰了。。。 哎!你永遠想象不到甲方憤怒的樣子,專案組每個人的祖宗都被問候到了。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200213162013337.png?#pic_center) 說了一些沒用的,腦子裡總想起這個事,不說不痛快,大家姑且就當笑話聽吧,下邊我們進入正題 --- #### 引言 前兩天有個學弟公眾號留言,說讓講講分散式事務,面試就掛在這個問題上。時下隨著微服務架構體系的流行,面試的題目也都慢慢開始升級,不再是早些年單純的問點SSH框架知識、資料結構了。`高併發`、`高可用`、`分散式服務治理`、`分散式檔案系統`、`分散式xxx`,反正和分散式沾邊的都會問點, 專案實際用不用不要緊,關鍵你得了解,是不是總有一種學不動了的感覺? --- #### 什麼是分散式事務? 我們看看百度上對於分散式事務的定義:分散式事務是指事務的參與者、支援事務的伺服器、資源伺服器以及事務管理器分別位於不同的分散式系統的不同節點之上。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200303183321411.png) 額~ 看了反而更懵逼了,簡單的畫個圖好讓大家理解一下,拿下單減庫存來說舉例:當系統的業務量很小時,“`一站式`”的系統完全可以滿足現有業務需求,所有的業務都共用一個數據庫,整個下單流程或許只用在一個方法裡同一個事務下操作資料庫即可。 此時所有操作都在一個事務裡,要麼全部提交,要麼全部回滾 。 ![圖糙理不糙](https://img-blog.csdnimg.cn/20200304100343959.png#pic_center) 但隨著業務量不斷增長,“`一站式`”系統漸漸扛不住巨大的流量,就需要對資料庫進行分庫分表,將業務服務化拆分(`SOA`),就會分離出了訂單中心、使用者中心、庫存中心。而這樣就造成業務間相互隔離,每個業務都維護著自己的資料庫,資料的交換隻能進行RPC呼叫。 使用者再下單時,建立訂單和扣減庫存,需要同時對訂單DB和庫存DB進行操作。兩步操作必須同時成功,否則就會造成業務混亂,可此時我們只能保證自己服務的資料一致性,無法保證呼叫其他服務的操作是否成功,所以為了保證整個下單流程的資料一致性,就需要分散式事務介入。 ![圖糙理不糙](https://img-blog.csdnimg.cn/20200304100834158.png#pic_center) 在說分散式事務之前,先回憶一下事務的基本概念:事務是一個程式執行單元,裡面的所有操作要麼全部執行成功,要麼全部執行失敗。 一個事務有四個基本特性,也就是我們常說的(`ACID`)。 **`Atomicity`(原子性)** :事務是一個不可分割的整體,事務內所有操作要麼全做成功,要麼全失敗。 **`Consistency`(一致性)** :務執行前後,資料從一個狀態到另一個狀態必須是一致的(A向B轉賬,不能出現A扣了錢,B卻沒收到)。 **`Isolation`(隔離性)**: 多個併發事務之間相互隔離,不能互相干擾。 **`Durablity`(永續性)** :事務完成後,對資料庫的更改是永久儲存的,不能回滾。 上面這些知識點都是反反覆覆唸叨的概念,面試必背的東西。 #### 分散式事務解決方案 有困難就一定會有解決問題的辦法,什麼都難不倒聰明的程式設計師。 `XA協議`是一個基於資料庫的分散式事務協議,其分為兩部分:`事務管理器`和`本地資源管理器`。`事務管理器`作為一個全域性的排程者,負責對各個本地資源管理器統一號令`提交`或者`回滾`。二階提交協議(`2PC`)和三階提交協議(`3PC`)就是根據此協議衍生出來而來。如今`Oracle`、`Mysql`等資料庫均已實現了`XA介面`。 ##### 1、兩段提交(2PC) `兩段提交`顧名思義就是要進行兩個階段的提交:第一階段,準備階段(投票階段) ; 第二階段,提交階段(執行階段)。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200311150611301.png) > 上邊圖片源自網路,如有侵權聯絡刪除 下面還拿下單扣庫存舉例子,簡單描述一下兩段提交(2PC)的原理: 之前說過業務服務化(`SOA`)以後,一個下單流程就會用到多個服務,各個服務都無法保證呼叫的其他服務的成功與否,這個時候就需要一個全域性的角色(`協調者`)對各個服務(`參與者`)進行協調。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200311151400606.png) 一個下單請求過來通過`協調者`,給每一個`參與者`傳送`Prepare`訊息,執行本地資料指令碼但不提交事務。 如果`協調者`收到了`參與者`的失敗訊息或者超時,直接給每個`參與者`傳送`回滾(Rollback)`訊息;否則,傳送`提交(Commit)`訊息;`參與者`根據`協調者`的指令執行提交或者回滾操作,釋放所有事務處理過程中被佔用的資源,顯然`2PC`做到了所有操作要麼全部成功、要麼全部失敗。 **兩段提交(2PC)的缺點** 二階段提交看似能夠提供原子性的操作,但它存在著嚴重的缺陷 - **網路抖動導致的資料不一致:** 第二階段中`協調者`向`參與者`傳送`commit`命令之後,一旦此時發生網路抖動,導致一部分`參與者`接收到了`commit`請求並執行,可其他未接到`commit`請求的`參與者`無法執行事務提交。進而導致整個分散式系統出現了資料不一致。 - **超時導致的同步阻塞問題:** `2PC`中的所有的參與者節點都為`事務阻塞型`,當某一個`參與者`節點出現通訊超時,其餘`參與者`都會被動阻塞佔用資源不能釋放。 - **單點故障的風險:** 由於嚴重的依賴`協調者`,一旦`協調者`發生故障,而此時`參與者`還都處於鎖定資源的狀態,無法完成事務`commit`操作。雖然協調者出現故障後,會重新選舉一個協調者,可無法解決因前一個`協調者`宕機導致的`參與者`處於阻塞狀態的問題。 ##### 2、三段提交(3PC) 三段提交(3PC)是對兩段提交(2PC)的一種升級優化,`3PC`在`2PC`的第一階段和第二階段中插入一個準備階段。保證了在最後提交階段之前,各參與者節點的狀態都一致。同時在協調者和參與者中都引入超時機制,當`參與者`各種原因未收到`協調者`的commit請求後,會對本地事務進行commit,不會一直阻塞等待,解決了`2PC`的單點故障問題,但`3PC` 還是沒能從根本上解決資料一致性的問題。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200311173907495.png) > 上邊圖片源自網路,如有侵權聯絡刪除 3PC 的三個階段分別是`CanCommit`、`PreCommit`、`DoCommit` **CanCommit**:協調者向所有參與者傳送CanCommit命令,詢問是否可以執行事務提交操作。如果全部響應YES則進入下一個階段。 **PreCommit**:`協調者`向所有`參與者`傳送`PreCommit`命令,詢問是否可以進行事務的預提交操作,參與者接收到PreCommit請求後,如參與者成功的執行了事務操作,則返回`Yes`響應,進入最終commit階段。一旦參與者中有向協調者傳送了`No`響應,或因網路造成超時,協調者沒有接到參與者的響應,協調者向所有參與者傳送`abort`請求,參與者接受abort命令執行事務的中斷。 **DoCommit**: 在前兩個階段中所有參與者的響應反饋均是`YES`後,協調者向參與者傳送`DoCommit`命令正式提交事務,如協調者沒有接收到參與者傳送的ACK響應,會向所有參與者傳送`abort`請求命令,執行事務的中斷。 ##### 3、補償事務(TCC) 很多初學者總是被`TCC`、`2PC`、`3PC`這幾個概念搞混淆,傻傻分不清,實際上 `TCC`與 `2PC`、`3PC`一樣,都只是實現分散式事務的一種方案而已。 `TCC`(Try-Confirm-Cancel)又被稱`補償事務`,`TCC`與`2PC`的思想很相似,事務處理流程也很相似,但`2PC` 是應用於在DB層面,TCC則可以理解為在應用層面的`2PC`,是需要我們編寫業務邏輯來實現。 `TCC`它的核心思想是:"針對每個操作都要註冊一個與其對應的確認(Try)和補償(Cancel)"。 還拿下單扣庫存解釋下它的三個操作: **Try階段:** 下單時通過Try操作去扣除庫存預留資源。 **Confirm階段:** 確認執行業務操作,在只預留的資源基礎上,發起購買請求。 **Cancel階段:** 只要涉及到的相關業務中,有一個業務方預留資源未成功,則取消所有業務資源的預留請求。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200311174835104.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3hpbnpoaWZ1MQ==,size_16,color_FFFFFF,t_70) > 上邊圖片源自網路,如有侵權聯絡刪除 **TCC的缺點:** - 應用侵入性強:TCC由於基於在業務層面,至使每個操作都需要有 `try`、`confirm`、`cancel`三個介面。 - 開發難度大:程式碼開發量很大,要保證資料一致性 `confirm` 和 `cancel` 介面還必須實現冪等性。 #### 總結 很淺顯的介紹了一下2PC、3PC、TCC的概念,如有錯誤還望溫柔指正,分散式事務一直都是面試中比較熱點的問題,也是進階高階Java工程師必備的知識點。 --- [整理了一些Java方面的架構、面試資料(微服務、叢集、分散式、中介軟體等),有需要的小夥伴可以關注公眾號【程式設計師內點事】,無套路自行領取](https://mp.weixin.qq.com/s/7Sb-INOrSfQ00sxETLmNog) ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly91c2VyLWdvbGQtY2RuLnhpdHUuaW8vMjAyMC8yLzQvMTcwMGU0Mjk1MDQzMjQ0Yg?x-oss-process=image/for