避不開的分散式事務

Code綜藝圈 發表於 2021-07-26

前言

關於前面系列的文章已經說到分散式服務之間的通訊,則分散式事務接下來就是我們要一起學習的主題,走起。

資料庫事務在現有大大小小的系統中幾乎是避免不開的,或多或少總會有一些業務關聯在一塊;對於單機事務的應用場景和操作,相信小夥伴已經夠熟練了;隨著分散式、微服務的開發模式普及,分散式事務落地也成為了程式設計師的必備之技,接下來的幾篇一起來學習和實操。

正文

1. 事務回顧

1. 1 事務簡介

通俗一點理解就是將一組對資料的操作(增、刪、改、查)看做成一個邏輯單元,要麼都執行,要麼都不執行,確保資料一致性

1.2 事務特性(ACID)
  • 原子性(Atomicity)

    指事務內所有操作要麼一起執行成功,要麼都一起失敗(或者說是回滾);如事務經典轉賬案例:A給B轉賬,A把錢扣了,但B沒有收到;可見這種錯誤是不能接受的,最終會回滾,這也是原子性的重要性。

  • 一致性(Consistency)

    指事務執行前後的狀態一致,如事務經典轉賬案例:A給B互相轉賬,不管怎麼轉,最終兩者錢的總和還是不變;

  • 永續性(Durability)

    指事務一旦提交,資料就已經永久儲存了,不能再回滾;

  • 隔離性(Isolation)

    指多個併發事務之間的操作互不干擾,但是事務的併發可能會導致資料髒讀、不可重複讀、幻讀問題,根據業務情況,採用事務隔離級別進行對應資料讀問題處理。

1.3 事務隔離級別
  • 讀未提交(Read uncommitted)

    指一個事務讀取到其他未提交事務的資料。可能導致資料髒讀

    轉賬案例:A正在給B轉賬,本來轉的1000,A多輸入了個0,變成10000,但此事務還未提交,但此時B查詢到轉入的是10000,但A取消事務回滾之後,B又查詢不到轉入的資料。這種情況就是髒讀

  • 讀已提交(Read committed)

    指一個事務只能讀取到其他事務已提交的資料,從而解決了髒讀的問題。但可能導致資料不可重複讀

    轉賬案例:A要給B轉賬1000,A先檢視了一下餘額,有1000,然後開始給B轉錢,但此時A家裡電費通過開啟的自動繳費功能,自動從A賬戶扣除200繳納電費,並提交;當A轉賬準備提交,再次確認餘額時,錢少了200。這樣就導致同一個事務中多次查詢的結果不一致,這種情況就是不可重複讀

  • 可重複讀(Repeatable read)

    指事務只要一開啟,就不允許其他事務進行修改操作,從而解決了不可重複讀問題。但可能導致資料幻讀

    轉賬案例:A經常給B轉賬,到年底了,需要查賬,然後開啟了一個事務進行查詢統計,剛開始查詢只是10條轉賬記錄,正準備統計時,因為緊急情況A需要給B轉一筆錢應急,從而新增了一條新記錄,並提交;而查賬事務正在統計中,最後發現轉賬額和看到的10條轉賬記錄不匹配。這種情況就是幻讀

  • 序列化(Serializable )

    指事務之間只能序列話執行,就像佇列一樣,排隊進行,這樣就解決了幻讀的問題,但是這種級別的併發效能不高,非特殊需求,這種級別一般不用。

2. 分散式事務場景

一個專案對應一個資料庫,這種單機業務是平時處理的比較多的;這裡主要歸納一下會出現分散式事務的場景。

2.1 一個專案多個資料庫

避不開的分散式事務

這種情況一般是併發量不大,但資料量比較大的情況,就比如一些採集裝置資料做實時分析的系統,如感測器資料、電機狀態等,經過一段時間,資料量會很多,導致單個資料庫效率變低,所以通常會採用分業務儲存。

如上圖,如果出現需要操作DB1中資料的同時又需要操作DB2資料,確保兩次操作要麼都成功,要麼都失敗,這就需要事務,而這種和單一系統(一個專案,一個資料庫)的事務處理方式不一樣,得分散式事務進行處理。

2.2 多個專案一個資料庫

避不開的分散式事務

有些系統需要將業務分開開發和部署,便於程式碼管理和後期維護,在資料庫資源允許的情況下可以共用一個資料庫,在這種情況下如果有事務操作,同樣需要分散式事務進行處理。

2.3 多個專案多個資料庫

避不開的分散式事務

這種方式其實就是微服務模式,分業務劃分專案,每個業務對應一個資料庫,這種場景下專案之間的事務肯定是分散式的啦

3. CAP瞭解

3.1 簡介

對於分散式應用場景,有很多因素是不可控的,如網路不通、裝置當機、自然災害等原因導致服務不可用,這種情況對於分散式而言需要有一定的取捨,不能因為個別服務的不可用,導致整個系統崩掉。通常CAP理論會成為分散式指標的取捨,根據系統業務需求,滿足其中兩個指標即可。如下圖:

避不開的分散式事務

CAP是Consistency(一致性)、Availability(可用性)、PartitionTolerance(分割槽容錯性)三個詞的縮寫,具體含義如下:

  • C(Consistency-一致性):是指在寫操作之後,任意節點進行讀取時,都能一致獲取到最新的資料狀態。為了保證資料一致性,在同步資料時會就資源短時進行鎖定,目的為了避免獲取的老的資料,導致資料不一致情況,但這樣就會導致服務在短時間內不可用。
  • A(Availability-可用性):是指發起任何操作時都可以得到響應結果,不會出現響應超時或響應錯誤。就算是資料在同步過程中也要保證可用,即寧可拿到舊資料也不要報錯。
  • P(PartitionTolerance-分割槽容錯性):這裡的分割槽是指網路分割槽,通常分散式系統,各節點會部署到不同子網,由於網路具有不可控性,可能會導致節點之間的通訊失敗;但在設計此類系統時,應該考慮這種情況,保證提供正常的服務,這其實可以理解為平時我們們說的高可用;這個指標是分散式系統必備的,不然就不能叫高可用系統啦
3.2 CAP組合

其實通過上面的概述,C(一致性)和A(可用性)是互相排斥的,為了保證一致性,會鎖定資源導致短時間不可用,而可用性的要求就是必須對操作有對應的響應結果,就算得到的資料不是最新的也行,目的是保證可用。而P(分割槽容錯性)是分散式系統中必備指標,所以在分散式系統中經常的組合就是CP和AP

  • CP:放棄可用性,注重一致性和分割槽容錯性,其實這就是所謂的強一致性,可能在銀行跨行轉賬這種強一致業務場景才會用到,具體得根據業務場景做取捨。
  • AP:放棄強一致性,注重可用性和分割槽容錯性,這是現在絕大多數分散式業務場景的選擇,只要最後能保證最終一致性(Base理論)即可。
3.3 簡單理解一下BASE理論

BASE是Basically Available(基本可用),Soft State(軟狀態)和Eventually Consistent(最終一致性)三個短語的縮寫,是對AP的一種擴充套件,即當出現故障時允許部分服務不可用,但要保證核心服務正常。對於資料,允許一定時間內不一致,通過中間狀態(軟狀態)過渡,最後保證最終一致即可

舉例說明:

Basically Available(基本可用):比如一個系統註冊使用者成功時需要傳送資訊通知,允許傳送資訊不成功,但註冊這個核心功能要保證可用。

Soft State(軟狀態):平時見得最多的軟狀態有:“支付中”、“資料處理中”等,這些狀態是為了滿足可用性和最終一致增加的過渡狀態。

Eventually Consistent(最終一致性):比如在購買商品時,支付的過程中會顯示“支付中”,最終會顯示“支付成功”,這個時候其實就保證最終你的賬戶和收款賬戶這個事務最終一致了,這種事務可以理解為“柔性事務”。

4. 分散式事務常用的解決方案

  • 2PC(Two-phase commit protocol),又稱二階段提交,是一種強一致性解決方案。對其進行補充的還有一個叫3PC的解決方案。
  • TCC(Try Confirm Cancel),補償事務。
  • 本地訊息表
  • 訊息事務
  • 最大努力通知

這裡先不細說,後續逐個擊破,最終還是要用程式碼落地。

總結

這篇只是一個開端,主要是大概回顧一下分散式事務中常遇到的知識點,後續主要是針對各個解決方案的落地,一起擼碼。

一個被程式搞醜的帥小夥,關注"Code綜藝圈",和我一起學~~~

圖片