章節(jié)歸屬
1、背景
伴隨著高性能的分布式系統(tǒng)演進(jìn)琴昆,我們必然會(huì)經(jīng)歷 通過橫向擴(kuò)展節(jié)點(diǎn) 提高非熱點(diǎn)數(shù)據(jù)的并發(fā)性能;而橫向擴(kuò)展節(jié)點(diǎn)實(shí)際是如下2方面的擴(kuò)展變化:
- 擴(kuò)展功能節(jié)點(diǎn)(對(duì)應(yīng)應(yīng)用的微服務(wù)化改造)
- 擴(kuò)展數(shù)據(jù)節(jié)點(diǎn)(對(duì)應(yīng)增加數(shù)據(jù)分片)
這些變化自然就引發(fā) 原來調(diào)用一個(gè)服務(wù)的一個(gè)接口就完成的功能馆揉,現(xiàn)在需要協(xié)同調(diào)用多個(gè)服務(wù)的多個(gè)接口才能完成业舍。相信我們都遇到過因網(wǎng)絡(luò)、機(jī)器升酣、程序等不可靠舷暮,引發(fā)的數(shù)據(jù)一致性的問題。而數(shù)據(jù)的一致性與系統(tǒng)的可擴(kuò)展性和高可用同樣重要 是【基礎(chǔ)IT架構(gòu)】支撐業(yè)務(wù)高質(zhì)量轉(zhuǎn)型升級(jí)的重點(diǎn)也是難點(diǎn)噩茄。從螞蟻金服的分布事務(wù)產(chǎn)品十幾年的Roadmap可以看出其在數(shù)據(jù)一致性方面的堅(jiān)持和不易(如今能快速使用他們的積累下面,幸甚至哉!)绩聘,如下圖所示:
從官宣得知沥割,螞蟻金服從微服務(wù)演進(jìn)開始至今,大量的應(yīng)用采用了TCC事務(wù)模型凿菩,2017年推出了FMT模式机杜,類比即Seata中的AT模式。
2衅谷、起源
既然10年時(shí)間都是TCC模式椒拗,為什么會(huì)推出FMT(AT)模式呢,并且Seata官方也首推AT模式获黔,注意AT是 Auto Transaction 的縮寫蚀苛,這個(gè)話題我覺得可以借助汽車從手動(dòng)擋到自動(dòng)擋的演進(jìn)來討論,早期全是自動(dòng)擋汽車肢执,但2021年統(tǒng)計(jì)顯示自動(dòng)擋車占比超過80%枉阵,為什么會(huì)這樣呢:
- 自動(dòng)檔汽車比手動(dòng)檔汽車更容易操作
自動(dòng)檔汽車可以自動(dòng)匹配檔位與速度,而手動(dòng)檔汽車則需要根據(jù)行駛速度预茄,手動(dòng)實(shí)現(xiàn)檔位的轉(zhuǎn)換兴溜。因此,自動(dòng)檔汽車更容易操作耻陕,更方便駕駛拙徽,尤其是對(duì)于缺少駕車經(jīng)驗(yàn)的司機(jī)而言,自動(dòng)檔汽車是非常好的選擇诗宣。 - 自動(dòng)檔汽車駕車舒適度更高
自動(dòng)檔汽車不用進(jìn)行手動(dòng)換擋膘怕,不需要手和腳的密切配合。自動(dòng)檔汽車在駕駛時(shí)可以不用一直進(jìn)行換檔位召庞,只需掌控踩油門的深淺岛心,就可以輕松實(shí)現(xiàn)速度的轉(zhuǎn)換来破,因此,很大程度上可以提高駕車舒適度忘古。 - 自動(dòng)檔汽車安全系數(shù)更高
對(duì)于新手來講徘禁,讓駕駛者專注于駕駛,避免額外的操控髓堪,做的少就錯(cuò)的少送朱,錯(cuò)的少自然就降低事故率。
若將誕生于早期的TCC分布式事務(wù)模式類比成手動(dòng)擋駕駛模式干旁,那么Seata-AT模式就是當(dāng)下主流的自動(dòng)擋駕駛模式驶沼,正如有了自動(dòng)變速箱后,駕駛者不需要知曉離合器争群、檔位的存在回怜,不用關(guān)注離合器、檔位和油門三者之間那微妙協(xié)作祭阀;開發(fā)著不需要再去關(guān)心提供TCC三個(gè)方法鹉戚,并掌控他們之間的協(xié)作;這些繁瑣且難度高的事項(xiàng)由框架層托管专控,開發(fā)者只關(guān)注如何編寫SQL來實(shí)現(xiàn)業(yè)務(wù)邏輯即可抹凳。
3、核心思想
Seata AT 模式 是基于數(shù)據(jù)源代理實(shí)現(xiàn)的伦腐,是增強(qiáng)型2pc模式赢底;其核心思想就是由框架托管分布式事務(wù):通過代理DataSource中的Connection,攔截SQL執(zhí)行柏蘑,改變其原執(zhí)行邏輯幸冻,由代理引入額外的機(jī)制,加入額外的邏輯完成分布式事務(wù)咳焚。
4洽损、角色和職責(zé)
4.1、基于JDBC驅(qū)動(dòng)操作DB革半,提供服務(wù)
跟正常寫業(yè)務(wù)服務(wù)沒有區(qū)別碑定。
4.2、角色
Seata-AT模式的實(shí)現(xiàn)中有3個(gè)重要角色
TC (Transaction Coordinator) - 事務(wù)協(xié)調(diào)者
維護(hù)全局和分支事務(wù)的狀態(tài)又官,驅(qū)動(dòng)全局事務(wù)提交或回滾延刘。
TM (Transaction Manager) - 事務(wù)管理器(發(fā)起方)
定義全局事務(wù)的范圍:開始全局事務(wù)、提交或回滾全局事務(wù)六敬。
RM (Resource Manager) - 資源管理器(參與者)
提供TCC服務(wù)碘赖,與TC交談以注冊(cè)分支事務(wù)和報(bào)告分支事務(wù)的狀態(tài),并驅(qū)動(dòng)分支事務(wù)提交或回滾。
4.3普泡、二階段的職責(zé)分工
AT 模式對(duì)業(yè)務(wù)無任何侵入播掷,其一階段和二階段的提交\回滾均由 Seata 框架自動(dòng)生成,用戶只需編寫“業(yè)務(wù) SQL”劫哼,便能輕松接入分布式事務(wù)叮趴。
4.3.1 第一階段:
如下圖所示,Seata 會(huì)攔截“業(yè)務(wù) SQL”权烧,首先解析 SQL 語義,找到“業(yè)務(wù) SQL”要更新的業(yè)務(wù)數(shù)據(jù)伤溉,在業(yè)務(wù)數(shù)據(jù)被更新前般码,將其保存成“before image”,然后執(zhí)行“業(yè)務(wù) SQL”更新業(yè)務(wù)數(shù)據(jù)乱顾,在業(yè)務(wù)數(shù)據(jù)更新之后板祝,再將其保存成“after image”,最后生成行鎖走净。以上操作全部在一個(gè)本地?cái)?shù)據(jù)庫(kù)事務(wù)內(nèi)完成券时,這樣保證了一階段操作的原子性。
第一階段總結(jié)來說即是:業(yè)務(wù)sql和記錄回滾日志的sql在同一個(gè)本地事務(wù)中提交伏伯,提交后即釋放本地連接資源橘洞。
4.3.2. 第二階段
4.3.2.1 二階段-提交
因?yàn)椤皹I(yè)務(wù) SQL”在一階段已經(jīng)提交至數(shù)據(jù)庫(kù), 所以 Seata 框架只需將一階段保存的快照數(shù)據(jù)和行鎖刪掉说搅,完成數(shù)據(jù)清理即可炸枣。
4.3.2.2 二階段-回滾
Seata 需要回滾一階段已經(jīng)執(zhí)行的“業(yè)務(wù) SQL”,還原業(yè)務(wù)數(shù)據(jù)弄唧∈食Γ回滾方式便是用“before image”還原業(yè)務(wù)數(shù)據(jù);但在還原前要首先要校驗(yàn)臟寫候引,對(duì)比“數(shù)據(jù)庫(kù)當(dāng)前業(yè)務(wù)數(shù)據(jù)”和 “after image”侯养,如果兩份數(shù)據(jù)完全一致就說明沒有臟寫,可以還原業(yè)務(wù)數(shù)據(jù)澄干,如果不一致就說明有臟寫逛揩,出現(xiàn)臟寫就需要轉(zhuǎn)人工處理。
第二階段總結(jié)來說即是:TC向RM發(fā)起提交或回滾傻寂;提交的話通過異步進(jìn)行回滾日志的自動(dòng)清理息尺,事務(wù)得以馬上結(jié)束;回滾的話疾掰,通過一階段的回滾日志搂誉,自動(dòng)生成并執(zhí)行補(bǔ)償回滾的數(shù)據(jù)操作。
5静檬、工作原理
5.1炭懊、整體架構(gòu)
Seata-AT模式整體架構(gòu)如下圖所示:
5.2并级、核心流程
5.2.1、第一階段
以一個(gè)原本有100塊的賬戶扣掉10塊錢為例:update account seg balance=balance-10 WHERE uId='001'
- 解析SQL:解析得到操作類型侮腹、表和條件嘲碧,這里SQL操作類型是update,表是account父阻,條件是uid='001' 信息
- 生成before image:從 account表中檢索uId='001'的賬戶在執(zhí)行update之前的余額愈涩,得到了100,即before image的結(jié)果集加矛,作為回滾時(shí)使用的數(shù)據(jù)
- 執(zhí)行業(yè)務(wù)SQL:update account set balance=balance-10 where uId='001'
- 生成after image:從 account表中檢索uId='001'的賬戶的在執(zhí)行update之后的余額履婉,得到了90,即after image的結(jié)果集斟览,作為回滾時(shí)用于比對(duì)判斷是否有臟寫的依據(jù)
- 記錄undolog:將前后鏡像組合毁腿,以 json格式壓縮一下存到 UNDO_LOG 表中
- 提交前,RM向TC注冊(cè)分支:這里會(huì)申請(qǐng) account 表中主鍵值等于 '001' 的記錄的全局鎖苛茂,鎖的粒度是:服務(wù)+表+記錄ID
- 提交本地事務(wù):將業(yè)務(wù)數(shù)據(jù)的更新和undolog的記錄 一并提交
- 將本地事務(wù)提交的結(jié)果上報(bào)給 TC
5.2.2已烤、第二階段-提交
- TM 向 TC 發(fā)起全局事務(wù)提交
- TC 向 各RM 發(fā)起分支提交(傳遞XID)
- RM 接收到請(qǐng)求后放入一個(gè)異步任務(wù)的隊(duì)列中,并立即返回TC提交成功
- 異步任務(wù)批量地刪除相應(yīng) undolog
5.2.3妓羊、第二階段-回滾
- 收到 TC 的分支回滾請(qǐng)求胯究,開啟一個(gè)本地事務(wù)
- 通過 XID 和 Branch ID 找到相應(yīng)的 undolog
- 校驗(yàn)臟寫:后鏡像與當(dāng)前數(shù)據(jù)庫(kù)數(shù)據(jù)比較,如有不同則說明已被當(dāng)前全局事務(wù)外的動(dòng)作做了修改侍瑟,此時(shí)需根據(jù)配置策略來處理
- 還原數(shù)據(jù):根據(jù)前后鏡像唐片,生成逆向SQL并“回滾”(相當(dāng)于重新寫入一次)
- 刪除undolog
- 提交本地事務(wù),并把本地事務(wù)的執(zhí)行結(jié)果(即分支事務(wù)回滾的結(jié)果)上報(bào)給 TC
5.3涨颜、注意事項(xiàng)
- 空回滾费韭、 防懸掛、 冪等控制
在TCC模式下,需要考慮 空回滾、 防懸掛悄蕾、 冪等控制的情況习绢。但是在AT模式下芋肠,不需要有業(yè)務(wù)層去關(guān)注這些問題,因?yàn)榭蚣芸梢酝ㄟ^AT模式中生成的前后鏡像,自動(dòng)處理以上問題。 - 數(shù)據(jù)隔離
本地事務(wù)的支持是seata實(shí)現(xiàn)at模式的必要條件逻翁,在數(shù)據(jù)庫(kù)本地事務(wù)隔離級(jí)別 讀已提交(Read Committed) 或以上的基礎(chǔ)上,Seata(AT 模式)的默認(rèn)全局隔離級(jí)別是 讀未提交(Read Uncommitted) 捡鱼,通過 SELECT FOR UPDATE 語句實(shí)現(xiàn)讀已提交 八回。
6、總結(jié)
跟TCC事務(wù)模式對(duì)比AT自動(dòng)事務(wù)模式能帶來這些好處:
- 難度低
AT模式 對(duì)于缺少分布式事務(wù)經(jīng)驗(yàn)的開發(fā)者來說,開發(fā)者僅按照傳統(tǒng)開發(fā)模式缠诅,通過簡(jiǎn)單的注解就可委托框架層補(bǔ)充實(shí)現(xiàn)整個(gè)分布式事務(wù)溶浴,甚至不需要了解分布式事務(wù)的原理。 - 效率高
AT模式管引,開發(fā)者專注于業(yè)務(wù)sql士败,只需要加注解就可實(shí)現(xiàn)分布式事務(wù),而無需處理如TCC模式下的服務(wù)邏輯需拆分為try 褥伴、confirm和cancel三個(gè)部分谅将;因此,很大程度上可以提高開發(fā)效率重慢。 - 更安全
拿TCC事務(wù)模型來說戏自,要求開發(fā)者將服務(wù)拆分為try 、confirm和cancel三個(gè)部分伤锚,同時(shí)還要求開發(fā)者自身有縝密的設(shè)計(jì)和嚴(yán)謹(jǐn)?shù)拇a來控制事務(wù)安全,應(yīng)對(duì)空回滾志衣、冪等屯援、懸掛等問題,并兼顧性能 念脯;而開發(fā)者對(duì)分布式事務(wù)的掌握程度不盡相同狞洋,自然實(shí)現(xiàn)的質(zhì)量也很難保證。
缺點(diǎn):
- 性能損耗
前后兩次查詢绿店,以及與TC的RPC通信吉懊,以及undo_log的寫入,會(huì)增加更多的開銷假勿。 - 熱點(diǎn)數(shù)據(jù)
全局鎖雖然是行鎖借嗽,但對(duì)熱點(diǎn)數(shù)據(jù)的讀寫依然不友好。