分佈式事務

場景

分佈式系統中,服務之間存在相互調用,一個分佈式事務會包含多個本地事務(數據庫事務)。
舉個常見的例子:支付寶餘額還花唄操作,餘額賬戶還款花唄賬戶人民幣100元,存在一個扣款操作,一個還款操作。餘額賬戶和花唄賬戶存在不同的數據庫中,是不同的事務,如何保證還款操作的事務一致性?如何處理扣款事務和還款事務?

理論

要理解分佈式事務,首先要先了解一下事務。
事務:一組操作,要麼全部執行,要麼都不執行。
事務的 ACID 是通過 InnoDB 日誌和鎖來保證。事務的隔離性是通過數據庫鎖的機制實現的,持久性通過 Redo Log(重做日誌)來實現,原子性和一致性通過 Undo Log 來實現
事務的四個特性:ACID
A原子性:事務最小單位,不可分割
C一致性:事務只能從一個一致性的狀態轉移到另外一個一致性的狀態
I隔離型:事務之間不能互相干擾,事務提交之前對其他事務是不可見的
D持久性:事務一旦提交,數據的改變是永久的

再說一下分佈式系統
百度百科的定義:分佈式系統(distributed system)是建立在網絡之上的軟件系統。通俗一點的解釋:一個系統拆分成多個子系統,部署在不同的服務器上,通過約定的協議進行通信。
這就涉及到不同的子服務之間溝通協作的問題。這些問題是什麼,如何解決這些問題,分佈式計算領域有一個公認的CAP原理。另一個BASE理論是對CAP中一致性和可用性的權衡的結果。

CAP理論

在一個分佈式系統(指互相連接並共享數據的節點的集合)中,當涉及讀寫操作時,只能保證一致性(Consistence)、可用性(Availability)、分區容錯性(Partition Tolerance)三者中的兩個,另外一個必須被犧牲。
C一致性:對某個指定的客戶端來說,讀操作保證能夠返回最新的寫操作結果。
A可用性:非故障的節點在合理的時間內返回合理的響應
P分區容錯性:當出現網絡分區後,系統能夠繼續“履行職責”
分佈式系統中CAP中的P是必選項,所以分佈式系統只能選擇CP架構或者AP架構

BASE理論

BASE 是指基本可用(Basically Available)、軟狀態( Soft State)、最終一致性( Eventual Consistency),核心思想是權衡一致性和可用性,捨棄強一致性,通過適合的方式達到最終一致性。
基本可用:分佈式系統出故障之後,允許部分可用。響應時間延長,功能上做適當的降級。
軟狀態:允許出現中間狀態,但中間狀態不會影響系統的整體可用。與CAP中的C一致性理論不符合
最終一致性:系統所有數據節點,經過一段時間之後,都可以達到一致的狀態

一致性和可用性之間作權衡。於是就出現了很多一致性協議

基於XA的兩階段提交

XA協議是一個分佈式事務協議,規定了事務管理器和本地資源管理器的接口。由兩部分組成,事務管理器和本地資源管理器。
第一階段爲投票階段:事務管理器會向所有的本地資源管理器發起CanCommit(預備)請求,本地資源管理器會執行事務操作,記錄日誌,但不提交,成功則向事務管理器回覆YES(就緒)消息,同意操作;如果不成功,則發送NO(失敗)消息,終止操作。第二階段,如果事務管理器收到YES消息,則向本地資源管理器發送DoCommit請求,本地資源管理器提交事務,將結果返回;如果收到No,則回滾,將結果返回。
xa
缺點是性能不理想,無法滿足高併發需求。

三階段提交

TCC補償型事務

Try階段:嘗試執行,完成所有業務檢查,鎖定必須的資源
Confirm階段:確認業務執行,不做檢查,正常情況下一定成功的,confirm接口需要滿足冪等,失敗後嘗試
Cancel階段:取消執行,釋放鎖定的資源,cancel接口也需要保證冪等性。
舉個例子:10元購買一瓶水,
Try階段:完成所有業務檢查,鎖定賬戶的10元和一瓶水的庫存
Confirm階段:檢查通過,執行下單操作,重試保證成功
Cancel階段:檢查失敗,釋放鎖定資源

本地消息表

將需要分佈式處理的事務通過消息或者日誌的方式異步執行,消息或日誌可以存到本地文件、數據庫或消息隊列中,再通過業務規則進行失敗重試,需要保證各服務的接口是冪等的。
本地消息表和業務數據處於同一個本地事務中,所以一定可以提交成功。

可靠消息最終一致性

基於MQ實現。支持事務消息的MQ:rocketmq
在這裏插入圖片描述
1.A服務向MQ發送一條prepared消息
2.A服務執行本地事務
3.A服務向MQ發送提交消息,MQ發送消息到B服務,B服務執行本地事務
4.如果B事務執行失敗,返回MQ異常信息,MQ會重新發送消息

失敗的情況
1失敗,直接回滾
2失敗,直接回滾。A服務需要實現一個mq的回調,用於檢查2是否成功,如果失敗,會回滾prepared消息。
3失敗,消息會重投,保證B執行成功

實踐

可靠消息最終一致性
安裝啓動rocketmq

docker run -d -p 9876:9876 -v `pwd`/data/namesrv/logs:/root/logs -v `pwd`/data/namesrv/store:/root/store --name rmqnamesrv -e "MAX_POSSIBLE_HEAP=100000000" rocketmqinc/rocketmq sh mqnamesrv
docker run -d -p 10911:10911 -p 10909:10909 -v `pwd`/data/broker/logs:/root/logs -v `pwd`/data/broker/store:/root/store --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" -e "MAX_POSSIBLE_HEAP=200000000" rocketmqinc/rocketmq sh mqbroker

控制檯

docker run -e "JAVA_OPTS=-Drocketmq.namesrv.addr=172.17.0.3:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" -p 8080:8080 -t styletang/rocketmq-console-ng

總結

業務服務接口很多都涉及到冪等
下次總結一下實現接口冪等性的注意點

第一篇學習記錄,實踐部分沒完成,半成品,相當於筆記。有問題感謝指出,會盡快修復掉。
感受:真正花時間把知識彙總起來實在是太難了,要堅持,下次找個熟悉的知識點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章