什麼是事務?
是數據庫執行過程中的一個邏輯單位,由一個有限的數據庫操作序列構成。
事務的ACID四大特性:
原子性(Atomicity):事務作爲一個整體被執行。
一致性(Consistency):從一個一致的狀態轉換到另一個一致的狀態。
隔離性(Isolation):多個事務併發執行時,併發事務之間互相影響的程度。
持久性(Durability):已被提交的事務對數據庫的修改應該永久保存在數據庫中。
什麼是分佈式事務
事務的參與者、支持事務的服務器、資源服務器以及事務管理器分別位於不同的分佈式系統的不同節點智商,且屬於不同的應用,分佈式事務需要保證這些操作要麼全部成功,要麼全部失敗。
分佈式事務解決方案
- XA兩階段提交2PC (強一致性)
涉及兩個角色
一個事務協調者:負責協調多個參與者進行事務投票及提交(回滾)
多個事務參與者:本地事務執行者
處理的兩個階段
1、投票階段:協調者將通知事務參與者準備提交或取消事務,然後進入表決過程。參與者將告知協調者自己的決策:同意(未提交)或取消(執行故障)
2、提交階段:收到參與者的通知後,協調者再向參與者發出通知,根據反饋情況決定各參與者是否要提交還是回滾
優點:儘量保證數據的強一致,適合對數據強一致要求很高的關鍵領域
缺點:
- 同步阻塞:執行過程中,各節點是事務阻塞型。所有的事務,等待最長事務的執行。
- 單點故障:協調者發生故障,參與者會一直阻塞
無法解決的問題:協調者發出commit消息之後宕機,唯一接收到這條消息的參與者同時也宕機。那麼即使協調者通過選舉協議產生了新的協調者,這條事務的狀態也是不確定的,沒人知道事務是否被提交了。
- 三段提交3PC(強一致)
兩段提交的升級版
1、CanCommit階段:詢問階段
2、PreCommit階段:事務執行但不提交階段
3、doCommit階段:事務提交階段
優點: 相對2PC,3PC主要解決單點故障問題,並減少阻塞,因爲一旦參與者無法及時收到來自協調者的信息之後,他會默認執行commit。而不會一直持有事務資源並處於阻塞狀態。
缺點: 由於網絡原因,還是會存在數據不一致問題。
- TCC補償機制(強一致)
核心思想:針對每個操作,都註冊一個與其對應的確認和補償操作。
例如: 小紅要向小白轉賬100元,執行流程:
- 首先在 Try 階段,要先調用遠程接口檢查小紅的賬戶餘額是否大於等於100元,若足夠則對餘額進行凍結,檢查小白的賬戶狀態是否正常。
- 在 Confirm 階段,執行遠程調用的轉賬的操作,扣除小紅賬戶100元,小白賬戶加100元。
- 如果第2步執行成功,那麼轉賬成功,小紅賬戶解凍,流程結束。
- 如果第二步執行失敗,則調用服務A的Cancel方法,賬戶餘額回滾100元及解凍小紅賬戶,同時調用服務B的Cancel方法,賬戶扣除100元。
優點: 跟2PC比起來,實現以及流程相對簡單了一些。
缺點:
- 在2 3 4步中都有可能失敗,從而導致數據不一致。
- TCC屬於應用層的一種補償方式,需要程序員在實現的時候多寫很多補償的代碼,複雜業務場景下代碼邏輯非常複雜。
- 冪等性無法確保。
- 本地消息表(MQ+Table)(最終一致)
工作流程:
- 消息生產方,需要額外建一個消息表,並記錄消息發送狀態。消息表和業務數據要在一個事務裏提交,也就是說他們要在一個數據庫裏面。然後消息會經過MQ發送到消息的消費方。如果消息發送失敗,會進行重試發送。
- 消息消費方,需要處理這個消息,並完成自己的業務邏輯。此時如果本地事務處理成功,表明已經處理成功了,如果處理失敗,那麼就會重試執行。如果是業務上面的失敗,可以給生產方發送一個業務補償消息,通知生產方進行回滾等操作。
- 生產方和消費方定時掃描本地消息表,把還沒處理完成的消息或者失敗的消息再發送一遍。
優點: 一種非常經典的實現,避免了分佈式事務,實現了最終一致性。
缺點: 消息表會耦合到業務系統中,如果沒有封裝好的解決方案,會有很多雜活需要處理。
- 事務消息(RocketMQ)(最終一致)
有一些第三方的MQ是支持事務消息的,比如RocketMQ,他們支持事務消息的方式也是類似於採用的二階段提交,但是市面上一些主流的MQ都是不支持事務消息的,比如 RabbitMQ 和 Kafka 都不支持(RabbitMQ、Kafka基於ACK機制)。
以阿里的 RocketMQ 中間件爲例,流程爲:
- 發送一個事務消息,這個時候,RocketMQ將消息狀態標記爲Prepared,注意此時這條消息消費者是無法消費到的。
- 執行業務代碼邏輯。
- 確認發送消息,RocketMQ將消息狀態標記爲可消費,這個時候消費者才能真正消費到這條消息。
- 如果步驟3確認消息發送失敗,RocketMQ會定期掃描消息集羣中的事務消息,如果發現了Prepared消息,它會向消息發送端(生產者)確認。RocketMQ會根據發送端設置的策略來決定是回滾還是繼續發送確認消息。這樣就保證了消息發送與本地事務同時成功或同時失敗。
優點: 實現了最終一致性,不需要依賴本地數據庫事務。
缺點: 目前主流MQ中只有RocketMQ支持事務消息。
- Seata
核心組件:
- Transaction Coordinator (TC): 事務協調器,維護全局事務的運行狀態,負責協調並驅動全局事務的提交或回滾。
- Transaction Manager ™: 控制全局事務的邊界,負責開啓一個全局事務,並最終發起全局提交或全局回滾的決議。
- Resource Manager (RM): 控制分支事務,負責分支註冊、狀態彙報,並接收事務協調器的指令,驅動分支(本地)事務的提交和回滾。
工作流程:
- TM 向 TC 申請開啓一個全局事務,全局事務創建成功並生成一個全局唯一的事務ID(XID),XID 在微服務調用鏈路的上下文中傳播。
- RM 向 TC 註冊分支事務,接着執行這個分支事務並提交事務(重點:RM在此階段就已經執行了本地事務的提交/回滾),最後將執行結果彙報給TC。
- TM 根據 TC 中所有的分支事務的執行情況,發起全局提交或回滾決議。
- TC 調度 XID 下管轄的全部分支事務完成提交或回滾請求。