Seata 是什么?
Seata 是一款開(kāi)源的分布式事務(wù)解決方案,致力于提供高性能和簡(jiǎn)單易用的分布式事務(wù)服務(wù)。Seata 將為用戶(hù)提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶(hù)打造一站式的分布式解決方案。
AT 模式
前提
- 基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫(kù)。
- Java 應(yīng)用,通過(guò) JDBC 訪問(wèn)數(shù)據(jù)庫(kù)。
整體機(jī)制
兩階段提交協(xié)議的演變:
-
一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個(gè)本地事務(wù)中提交,釋放本地鎖和連接資源。
-
二階段:
- 提交異步化,非常快速地完成。
- 回滾通過(guò)一階段的回滾日志進(jìn)行反向補(bǔ)償。
寫(xiě)隔離
- 一階段本地事務(wù)提交前,需要確保先拿到?全局鎖?。
- 拿不到?全局鎖?,不能提交本地事務(wù)。
- 拿?全局鎖?的嘗試被限制在一定范圍內(nèi),超出范圍將放棄,并回滾本地事務(wù),釋放本地鎖。
以一個(gè)示例來(lái)說(shuō)明:
兩個(gè)全局事務(wù) tx1 和 tx2,分別對(duì) a 表的 m 字段進(jìn)行更新操作,m 的初始值 1000。
tx1 先開(kāi)始,開(kāi)啟本地事務(wù),拿到本地鎖,更新操作 m = 1000 - 100 = 900。本地事務(wù)提交前,先拿到該記錄的?全局鎖?,本地提交釋放本地鎖。 tx2 后開(kāi)始,開(kāi)啟本地事務(wù),拿到本地鎖,更新操作 m = 900 - 100 = 800。本地事務(wù)提交前,嘗試拿該記錄的?全局鎖?,tx1 全局提交前,該記錄的全局鎖被 tx1 持有,tx2 需要重試等待?全局鎖?。
tx1 二階段全局提交,釋放?全局鎖?。tx2 拿到?全局鎖?提交本地事務(wù)。
如果 tx1 的二階段全局回滾,則 tx1 需要重新獲取該數(shù)據(jù)的本地鎖,進(jìn)行反向補(bǔ)償?shù)母虏僮?#xff0c;實(shí)現(xiàn)分支的回滾。
此時(shí),如果 tx2 仍在等待該數(shù)據(jù)的?全局鎖,同時(shí)持有本地鎖,則 tx1 的分支回滾會(huì)失敗。分支的回滾會(huì)一直重試,直到 tx2 的?全局鎖?等鎖超時(shí),放棄?全局鎖?并回滾本地事務(wù)釋放本地鎖,tx1 的分支回滾最終成功。
因?yàn)檎麄€(gè)過(guò)程?全局鎖?在 tx1 結(jié)束前一直是被 tx1 持有的,所以不會(huì)發(fā)生?臟寫(xiě)?的問(wèn)題。
讀隔離
在數(shù)據(jù)庫(kù)本地事務(wù)隔離級(jí)別?讀已提交(Read Committed)?或以上的基礎(chǔ)上,Seata(AT 模式)的默認(rèn)全局隔離級(jí)別是?讀未提交(Read Uncommitted)?。
如果應(yīng)用在特定場(chǎng)景下,必需要求全局的?讀已提交?,目前 Seata 的方式是通過(guò) SELECT FOR UPDATE 語(yǔ)句的代理。
SELECT FOR UPDATE 語(yǔ)句的執(zhí)行會(huì)申請(qǐng)?全局鎖?,如果?全局鎖?被其他事務(wù)持有,則釋放本地鎖(回滾 SELECT FOR UPDATE 語(yǔ)句的本地執(zhí)行)并重試。這個(gè)過(guò)程中,查詢(xún)是被 block 住的,直到?全局鎖?拿到,即讀取的相關(guān)數(shù)據(jù)是?已提交?的,才返回。
出于總體性能上的考慮,Seata 目前的方案并沒(méi)有對(duì)所有 SELECT 語(yǔ)句都進(jìn)行代理,僅針對(duì) FOR UPDATE 的 SELECT 語(yǔ)句。
工作機(jī)制
以一個(gè)示例來(lái)說(shuō)明整個(gè) AT 分支的工作過(guò)程。
業(yè)務(wù)表:product
| id | bigint(20) | PRI |
| name | varchar(100) | |
| since | varchar(100) |
AT 分支事務(wù)的業(yè)務(wù)邏輯:
update product set name = 'GTS' where name = 'TXC';一階段
過(guò)程:
得到前鏡像:
| 1 | TXC | 2014 |
得到后鏡像:
| 1 | GTS | 2014 |
二階段-回滾
二階段-提交
附錄
回滾日志表
UNDO_LOG Table:不同數(shù)據(jù)庫(kù)在類(lèi)型上會(huì)略有差別。
以 MySQL 為例:
| branch_id | bigint PK |
| xid | varchar(100) |
| context | varchar(128) |
| rollback_info | longblob |
| log_status | tinyint |
| log_created | datetime |
| log_modified | datetime |
TCC 模式
回顧總覽中的描述:一個(gè)分布式的全局事務(wù),整體是?兩階段提交?的模型。全局事務(wù)是由若干分支事務(wù)組成的,分支事務(wù)要滿(mǎn)足?兩階段提交?的模型要求,即需要每個(gè)分支事務(wù)都具備自己的:
- 一階段 prepare 行為
- 二階段 commit 或 rollback 行為
根據(jù)兩階段行為模式的不同,我們將分支事務(wù)劃分為?Automatic (Branch) Transaction Mode?和?Manual (Branch) Transaction Mode.
AT 模式(參考鏈接 TBD)基于?支持本地 ACID 事務(wù)?的?關(guān)系型數(shù)據(jù)庫(kù):
- 一階段 prepare 行為:在本地事務(wù)中,一并提交業(yè)務(wù)數(shù)據(jù)更新和相應(yīng)回滾日志記錄。
- 二階段 commit 行為:馬上成功結(jié)束,自動(dòng)?異步批量清理回滾日志。
- 二階段 rollback 行為:通過(guò)回滾日志,自動(dòng)?生成補(bǔ)償操作,完成數(shù)據(jù)回滾。
相應(yīng)的,TCC 模式,不依賴(lài)于底層數(shù)據(jù)資源的事務(wù)支持:
- 一階段 prepare 行為:調(diào)用?自定義?的 prepare 邏輯。
- 二階段 commit 行為:調(diào)用?自定義?的 commit 邏輯。
- 二階段 rollback 行為:調(diào)用?自定義?的 rollback 邏輯。
所謂 TCC 模式,是指支持把?自定義?的分支事務(wù)納入到全局事務(wù)的管理中。
Saga 模式
Saga模式是SEATA提供的長(zhǎng)事務(wù)解決方案,在Saga模式中,業(yè)務(wù)流程中每個(gè)參與者都提交本地事務(wù),當(dāng)出現(xiàn)某一個(gè)參與者失敗則補(bǔ)償前面已經(jīng)成功的參與者,一階段正向服務(wù)和二階段補(bǔ)償服務(wù)都由業(yè)務(wù)開(kāi)發(fā)實(shí)現(xiàn)。
理論基礎(chǔ):Hector & Kenneth 發(fā)表論? Sagas (1987)
適用場(chǎng)景:
- 業(yè)務(wù)流程長(zhǎng)、業(yè)務(wù)流程多
- 參與者包含其它公司或遺留系統(tǒng)服務(wù),無(wú)法提供 TCC 模式要求的三個(gè)接口
優(yōu)勢(shì):
- 一階段提交本地事務(wù),無(wú)鎖,高性能
- 事件驅(qū)動(dòng)架構(gòu),參與者可異步執(zhí)行,高吞吐
- 補(bǔ)償服務(wù)易于實(shí)現(xiàn)
缺點(diǎn):
- 不保證隔離性(應(yīng)對(duì)方案見(jiàn)用戶(hù)文檔)
總結(jié)
以上是生活随笔為你收集整理的Seata 是什么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 瞬时速率和瞬时速度的区别与联系(瞬时速率
- 下一篇: springCloud负载均衡Ribbo