根據業務需求需要對業務進行拆分,例如將一個大應用拆分成用戶模塊,訂單模塊,商品模塊,每個模塊都有自己的數據庫,在用戶購買商品的時候需要扣減商品模塊庫存,在訂單模塊添加訂單數據,這時候需要保證這兩個數據庫操作在同一個事務中完成,因此就出現了分布式事務
1. LCN事務模式
一、原理介紹:
LCN模式是通過代理Connection的方式實現對本地事務的操作,然后在由TxManager統一協調控制事務。當本地事務提交回滾或者關閉連接時將會執行假操作,該代理的連接將由LCN連接池管理。
二、模式特點:
該模式對代碼的嵌入性為低。
該模式僅限於本地存在連接對象且可通過連接對象控制事務的模塊。
該模式下的事務提交與回滾是由本地事務方控制,對於數據一致性上有較高的保障。
該模式缺陷在於代理的連接需要隨事務發起方一共釋放連接,增加了連接占用的時間。
2. TCC事務模式
一、原理介紹:
TCC事務機制相對於傳統事務機制(X/Open XA Two-Phase-Commit),其特征在於它不依賴資源管理器(RM)對XA的支持,而是通過對(由業務系統提供的)業務邏輯的調度來實現分布式事務。主要由三步操作,Try: 嘗試執行業務、 Confirm:確認執行業務、 Cancel: 取消執行業務。
二、模式特點:
該模式對代碼的嵌入性高,要求每個業務需要寫三種步驟的操作。
該模式對有無本地事務控制都可以支持使用面廣。
數據一致性控制幾乎完全由開發者控制,對業務開發難度要求高。
3. TXC事務模式
一、原理介紹:
TXC模式命名來源於淘寶,實現原理是在執行SQL之前,先查詢SQL的影響數據,然后保存執行的SQL快走信息和創建鎖。當需要回滾的時候就采用這些記錄數據回滾數據庫,目前鎖實現依賴redis分布式鎖控制。
二、模式特點:
該模式同樣對代碼的嵌入性低。
該模式僅限於對支持SQL方式的模塊支持。
該模式由於每次執行SQL之前需要先查詢影響數據,因此相比LCN模式消耗資源與時間要多。
該模式不會占用數據庫的連接資源。
————————————————
為了解決分布式一致性問題,前人在性能和數據一致性的權衡過程中總結了許多經典的協議和算法。比較著名的有:2PC、3PC、TCC、Paxos、Raft、Zab、ISR。除了這些之外,業界用的最多的其實是基於MQ實現的。
2PC(Two Phase Commit)兩階段提交:一般說的兩階段提交是基於XA協議的。另外JTA協議的也比較常見。
XA是一個分布式事務協議。它大致分為兩部分:事務管理器和本地資源管理器。其中本地資源管理器往往由數據庫實現,比如Oracle、DB2都實現了XA接口。MySQL對XA的支持不是很好。而事務管理器作為全局的調度者,負責各個本地資源的提交和回滾。
兩階段提交的優點是:原理簡單、實現方便。缺點是同步阻塞、單點問題、數據不一致。
3PC(Three Phrase Commit)三階段提交:分為CanCommit、PreCommit、Do Commit 三個階段。就是把兩階段提交的Phase 1分成兩個,預提交的時候如果有參與者返回No或者超時則中斷事務。
三階段提交的優點是降低參與者阻塞范圍,並能夠在出現單點故障后繼續達成一致。缺點是因為preCommit階段,在這個階段如果出現網絡分區,協調者無法與參與者正常通信,參與者仍然會進行實物提交,造成數據不一致。
TCC(Try-Confirm-Cancel)
Try:完成所有的檢查,預留必須資源
Confirm:使用Try階段預留的資源執行業務,如果執行出現異常,要重試
Cancel:釋放Try階段預留資源
TCC能夠對分布式事務中的各個資源進行分別鎖定,分別提交與釋放。適用於嚴格一致、執行時間短、實時性要求高的場景。
Paxos算法:之前看過《從Paxos到Zookeeper》那本書,沒怎么看明白。實現比較復雜,Zookeeper就是用這個來實現的分布式一致性。Paxos算法、Raft協議和Zab(Zookeeper Atomic Broadcast)協議都是一種通過多數投票來保證主備數據一致性的。
ISR(In-Sync Replicas)機制:Kafka使用了這個機制來保證數據一致性。ISR認為對於2f+1個副本來說,多數投票機制要求最多只能允許f個副本發生故障,如果要支持2個副本的容錯,則需要至少維持5個副本。
基本MQ實現是一種異步確保型的實現方案。將同步阻塞的事務變成異步的,避免了對數據庫事務的爭用。
2.X/OpenDTP事務模型
概念: X/Open是一個組織機構,定義了一套分布式事務標准,定義了規范的API接口角色:
AP application
RM resouces manager 資源管理器
TM transaction manager事務管理器
3.Mysql事務處理過程
3.1 記錄redo日志和undo日志,確保日志在磁盤上的持久化
3.2 更新數據記錄
3.3 提交事務,redo寫入commit記錄
4. 2PC協議
兩階段提交
階段一:提交事務請求
TM向所有的AP發送事務內容,詢問是否可以執行事務的提交操作,並等待各個AP的響應
執行事務
各個AP節點執行事務操作,將undo和redo信息記錄到事務日志中,盡量把提交過程中所消耗時間的操作和准備都提前完成后確保后續
事務提交的成功率
各個AP向TM反饋事務詢問的響應
各個AP成功執行了事務操作,那么反饋給TM yes的response;如果AP沒有成功執行事務,就反饋TM no的response
階段二: 執行事務提交
存在的問題
數據一致性問題:當AP和TM都宕機了,新選出來的TM不知道宕機的AP到底做了什么操作,如果根據剩下的兩個存活的AP的操作(commit或者abort)作為判斷,則很可能會因為宕機的操作和存活的操作不一致導致數據不一致
同步阻塞:第二階段中,如果所有的AP都宕機了.則TM只能阻塞等待AP的返回
5.3PC協議
階段一:canCommit:TM請求AP是否可以commit
階段二:preCommit
階段三:doCommit
6.分布式事務的實現
atomikos
7.MQ實現最終一致性
7.1消息重復消費解決方案
冪等校驗:在消費端新建一張表,使用唯一索引,消費數據前往數據表插入一條數據,如果插入成功則證明是第一次消費,如果插入失敗則證明已經不是第一次消費
日志表來判斷,或者通過狀態鎖來判斷,消費端創建一個日志表,消費時插入一個id和狀態,消費成功后去更新狀態
最終一致性模式:
查詢模式
補償模式:A調用B,失敗后自動重試,回滾原有操作,若不能自動重試則通知運營,人工補償(如人工對賬),或通知技術,監控,預警
TCC事務模型
8.LCN實現
服務消費方加注解 @TxcTransaction(timeout = 1000 * 10)
服務提供方獲取全局事務ID,並綁定到上下文
public int updateStock(OrderDO orderDO) {
//獲取全局事務ID,並綁定到上下文
String xid = RpcContext.getContext().getAttachment("xid");
TxcContext.bind(xid,null);
//執行自己的業務邏輯
int ret = jdbcTemplate.update("update stock set amount = amount - ? where product_id = ?",new Object[]{orderDO.getNumber(), orderDO.getProductId()});
TxcContext.unbind();
return ret;
}