來源:北大青鳥總部 2023年08月16日 08:59
提到事務兩個字,相信每一個開發人員都不陌生,從我們第一次開始接觸數據庫的時候,也就開始和事務打交道;而且是一直打交道,很可能要打一輩子交道。
為什么這么說呢,大家都知道,互聯網經過這么幾年快速的發展,互聯網技術也更新迭代了很多個版本,從最初的單體架構,到現在的分布式、微服務架構。
系統同樣也越來越復雜了,也就意味著問題越來越多了,原來單體架構時的一個小問題,放在了現在可能就是個大問題,需要系統的去解決,就不能像之前那樣,湊合過唄,畢竟夫妻和諧也是很重要的。
所以,單體階段可能只需要處理好數據庫的本地事務就可以了,但是到了分布式系統中,事務的事兒,也就變成了一件大事兒。
這篇文章,我們就來聊聊怎么來處理好這個大事兒,以及現在業內常用的解決方案有哪些?
什么是事務?
為了讓大家更好的能理解分布式的那些兒,我們還是先來回顧一下基礎的知識,比如第一個概念,什么是事務?咱們先來看下官方的解釋。
事務就是用戶定義的一系列數據庫操作,這些操作可以視為一個完成的邏輯處理工作單元,要么全部執行,要么全部不執行,是不可分割的工作單元。
說人話就是,事務是指程序中一系列嚴密的邏輯操作,而且所有操作必須全部成功完成,否則在每個操作中所做的所有更改都會被撤銷。
可以通俗理解為,大家要一起去搶銀行,要么都活著回來,要都永遠別回來了(牢里),就是一根繩上的螞蚱,不求同年同月同日生,但求同年同月同日死,聽上去還頗有些悲壯的感覺。
什么是分布式事務?
好了,事務我們知道怎么回事兒了,那什么是分布式事務呢?它有特殊在哪里呢?接下來我們就來一探究竟。
所謂分布式事務,就是指事務的資源分別位于不同的分布式系統的不同節點之上的事務;這個又是啥意思嘞?舉個栗子:
在早期單體架構時,通常情況下都是單庫單表場景,但是現在不是到了分布式環境下了嘛,業務數據非常龐大,所以當業務數據量達到單庫單表的極限時,就需要考慮分庫分表,將之前的單庫單表拆分成多庫多表;分庫分表之后,原來在單個數據庫上的事務操作,可能就變成跨多個數據庫的操作,此時就需要使用分布式事務。如果你還不明白,那就再舉個栗子:
我們的一個系統有 3個功能模塊:用戶模塊、商品模塊和訂單模塊,我們現在有一個操作需要按順序去調用完成這3個模塊中的接口,這個操作是一個整體,包含在一個事務中,要么同時成功要么同時失敗回滾。不成功便成仁,這個都沒有問題。
但是當我們把這個系統拆分成分布式系統架構的時候,事務就不是上面那么玩兒了,原來的用戶模塊、商品模塊和訂單模塊,都升級變成了用戶系統、商品系統和訂單系統,每個系統都是獨立部署,甚至擁有獨立的數據庫。
這么一來,分布式事務就復雜多了,怎么才能保證三個不同的系統,針對同一個操作能保持一致性,因為這個三個系統之間要么是RPC通訊,要么是HTTP通信,這就增加了事情的難度。不過,方法總比問題多,程序員是一幫聰明絕頂的人!
分布式事務常見解決方案
分布式事務常見的解決方案,現在通用的基本就如下這三種:
· 兩階段提交(2PC, Two Phase Commit)
· 本地消息表(eBay模式)
· 補償模式TCC
接下來我們就分別來看下幾種解決方案的特點。
兩階段提交(2PC,Two Phase Commit)方案
我們先來看下兩階段提交,兩階段提交其實就是為了保證分布在不同節點上的分布式事務的一致性,我們需要引入一個協調者來管理所有的節點,負責各個本地資源的提交和回滾,并確保這些節點正確提交操作結果,若提交失敗則放棄事務。
它有兩個階段
· 第一階段:準備階段(prepare) 協調者通知參與者準備提交訂單,參與者開始投票。參與者完成準備工作向協調者回應Yes
· 第二階段:提交(commit)/回滾(rollback)階段 協調者根據參與者的投票結果發起最終的提交指令。如果有參與者沒有準備好則發起回滾指令
本地消息表(eBay模式)
本地消息表,為什么又稱為eBay模式呢?那是因為eBay的架構師Dan Pritchett,曾在一篇解釋BASE原理的論文《Base:AnAcid Alternative》中提到一個eBay分布式系統一致性問題的解決方案。
它的核心思想是將需要分布式處理的任務通過消息或者日志的方式來異步執行,消息或日志可以存到本地文件、數據庫或消息隊列,再通過業務規則進行失敗重試,它要求各服務的接口是冪等的。
本地消息表與業務數據表處于同一個數據庫中,這樣就能利用本地事務來保證在對這兩個表的操作滿足事務特性,并且使用了消息隊列來保證最終一致性。
· 在分布式事務操作的一方完成寫業務數據的操作之后向本地消息表發送一個消息,本地事務能保證這個消息一定會被寫入本地消息表中。
· 之后將本地消息表中的消息轉發到 Kafka 等消息隊列中,如果轉發成功則將消息從本地消息表中刪除,否則繼續重新轉發。
·在分布式事務操作的另一方從消息隊列中讀取一個消息,并執行消息中的操作。
TCC補償事務
TCC補償事務,全稱Try-Confirm-Cancel,又叫做柔性事務。TCC補償事務方案可能是目前最火的一種柔性事務方案了。它的核心思想是:針對每個操作,都要注冊一個與其對應的確認和補償(撤銷)操作。
關于TCC(Try-Confirm-Cancel)的概念,最早是由PatHelland于2007年發表的一篇名為《Lifebeyond Distributed Transactions:an Apostate’s Opinion》的論文提出。
在該論文中,TCC還是以Tentative-Confirmation-Cancellation命名。正式以Try-Confirm-Cancel作為名稱的是Atomikos公司,其注冊了TCC商標(外國人的版權意識真強)。
它也分三個階段:
· Try階段主要是對業務系統做檢測及資源預留。
· Confirm 階段主要是對業務系統做確認提交,Try階段執行成功并開始執行 Confirm階段時,默認 Confirm階段是不會出錯的。即:只要Try成功,Confirm一定成功。
· Cancel 階段主要是在業務執行錯誤,需要回滾的狀態下執行的業務取消,預留資源釋放。
好了,到這里基本就把分布式事務的事兒,翻了個底朝天,其實也就那么回事兒;理論都有了,剩下的就是我們自己在真實的業務場景中去實戰了!