本篇內(nèi)容介紹了“什么是seata源碼”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
為延津等地區(qū)用戶提供了全套網(wǎng)頁設計制作服務,及延津網(wǎng)站建設行業(yè)解決方案。主營業(yè)務為成都網(wǎng)站制作、成都做網(wǎng)站、延津網(wǎng)站設計,以傳統(tǒng)方式定制建設網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
本文沒有seata的使用方法,怎么使用seata可以參考官方示例,詳細的很。
本文基于v0.8.0版本,本文沒貼代碼。
seata中的三個重要部分:
TC:事務協(xié)調(diào)器,維護全局事務和分支事務的狀態(tài),驅(qū)動全局提交或回滾,就是seata的服務端。
TM:事務管理器,開始全局事務,提交或回滾全局事務。
RM:資源管理器,管理正在處理的分支事務的資源,向TC注冊并報告分支事務的狀態(tài),并驅(qū)動分支事務的提交或回滾。
TC啟動
RM發(fā)送jdbcUrl、applicationId和transactionServiceGroup三個參數(shù)向TC發(fā)起注冊,建立連接。入口是在DataSourceProxy
實例化的時候
TM發(fā)送applicationId和transactionServiceGroup兩個參數(shù)向TC發(fā)起注冊,建立連接。
全局事務發(fā)起者,就是我們加@GlobalTransactional
注解的方法,seata會代理我們的方法,通過以下步驟來完成全局事務。
發(fā)送全局事務開始請求到TC,TC返回xid(全局事務唯一id),將xid綁定到當前線程
執(zhí)行我們的業(yè)務邏輯
業(yè)務邏輯成功,發(fā)送全局事務commit請求到TC,如果失敗則重試
業(yè)務邏輯異常(可配置回滾規(guī)則,即哪些異常回滾),發(fā)送全局事務rollback請求到TC,如果失敗則重試
清理資源,事務結(jié)束
源碼閱讀入口:io.seata.spring.annotation.GlobalTransactionalInterceptor#invoke
rm需要代理我們項目中的數(shù)據(jù)源,這一步需要我們修改自己的代碼,如下:
@Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { return new DruidDataSource(); } /** * 需要將DataSourceProxy 設置為主數(shù)據(jù)源,否則事務無法回滾 */ @Primary @Bean("dataSource") public DataSource dataSource(DataSource druidDataSource) { return new io.seata.rm.datasource.DataSourceProxy(druidDataSource); }
代理數(shù)據(jù)源的主要目的是代理數(shù)據(jù)庫連接,這樣就可以控制分支事務的commit、rollback。
seate的rm-datasoure模塊中有這幾個代理類DataSourceProxy、ConnectionProxy、StatementProxy,通過代理jdbc中的這幾個類,讓我們的sql通過ExecuteTemplate來進行執(zhí)行,這個類就是我們了解seata怎么控制分支事務的入口。下面看分支事務的處理步驟:
將xid綁定到當前數(shù)據(jù)庫連接(xid怎么來的?在后面)
拿到sql執(zhí)行前數(shù)據(jù)庫表中的數(shù)據(jù)記錄beforeImage(只是受影響的數(shù)據(jù)及字段,通過解析我們的sql完成)
執(zhí)行我們的業(yè)務sql
拿到sql執(zhí)行后數(shù)據(jù)庫表中的數(shù)據(jù)記錄afterImage
用變動數(shù)據(jù)的主鍵值作為lockKey,并保存到當前數(shù)據(jù)庫連接中
將beforeImage和afterImage轉(zhuǎn)換成undo log,并保存到當前數(shù)據(jù)庫連接中
向TC發(fā)送全局鎖請求(帶著xid和lockKey),TC返回branchId,表示拿到了全局鎖,若不成功則重試(默認30次,每次間隔10ms);這個全局鎖的是為了防止多個用戶同時對同一數(shù)據(jù)進行修改,造成后面通過undo_log進行回滾操作時數(shù)據(jù)出錯;這個鎖在PhaseTwo完成后,TC會進行釋放。
將undoLog保存到數(shù)據(jù)庫的undo_log表中
提交數(shù)據(jù)庫事務
向TC報告當前分支事務commit的結(jié)果(失敗或成功),若報告不成功則重試(默認5次)
commit成功后,清理當前數(shù)據(jù)庫連接綁定的xid
commit失敗后,向上拋出異常,以便讓tm知道,進行全局事務的回滾
這是PhaseOne的整個過程,下面看PhaseTwo:
tc收到tm的全局事務提交或回滾請求后,會對這個全局事務中的所有分支事務進行通知,rm在收到通知后,進行回滾或者提交的操作
回滾:取出數(shù)據(jù)庫undo_log進行數(shù)據(jù)補償還原,成功后刪除undo_log;提交:直接刪除undo_log
返回tc處理結(jié)果
源碼閱讀入口: io.seata.rm.datasource.StatementProxy#execute
用dubbo的filter實現(xiàn)的,源碼:io.seata.integration.dubbo.TransactionPropagationFilter
原理就是:上游在filter中把xid放到RpcContext中,下游再從RpcContext拿到xid。
對RestTemplate和Feign的支持不在seata-all中,而是在spring-cloud-alibaba-seata中
源碼入口:
com.alibaba.cloud.seata.rest.SeataRestTemplateAutoConfiguration com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration
原理就是:上游通過攔截器將xid放到請求的header中,下游通過攔截器從header中拿到xid。
seata還支持很多RPC框架,如sofa-rpc、motan等。我們也可以通過類似的方法使seata支持我們自己的rpc框架。
如果是用 GlobalLock 修飾的本地業(yè)務方法,雖然該方法并非某個全局事務下的分支事務,但是它對數(shù)據(jù)資源的操作也需要先查詢?nèi)宙i,如果存在其他 Seata 全局事務正在修改,則該方法也需等待。所以,如果想要Seata 全局事務執(zhí)行期間,數(shù)據(jù)庫不會被其他事務修改,則該方法需要強制添加 GlobalLock 注解,來將其納入 Seata 分布式事務的管理范圍。
功能有點類似于 Spring 的 @Transactional 注解,如果你希望開啟事務,那么必須添加該注解,如果你沒有添加那么事務功能自然不生效,業(yè)務可能出 BUG;Seata 也一樣,如果你希望某個不在全局事務下的 SQL 操作不影響 AT 分布式事務,那么必須添加 GlobalLock 注解。
seata服務端支持zk、nacos、eureka等作為服務發(fā)現(xiàn),通過數(shù)據(jù)庫實現(xiàn)數(shù)據(jù)共享,全局事務Session信息、分支事務Session信息,全局鎖信息都是放在數(shù)據(jù)庫中
TCC和AT的不同主要體現(xiàn)在RM這邊,TC和TM都是一樣的。
TCC的RM不會代理我們的數(shù)據(jù)源了,而是由我們自己指定rollback和commit邏輯,在二階段中,TM在發(fā)起全局事務提交回滾時,RM只需要執(zhí)行我們指定的rollback和commit方法就行了。
這種模式就是我們業(yè)務代碼的變動要多些,效率是要比AT模式高些。
RM一階段源碼入口:io.seata.spring.tcc.TccActionInterceptor#invoke
RM二階段源碼入口:io.seata.rm.tcc.TCCResourceManager#branchCommit#branchRollback
“什么是seata源碼”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!