網站首頁 編程語言 正文
分布式事務
一、分布式事務的組成部分
- 事務參與者:對應的一個一個的微服務
- 資源服務器:對應一個個微服務的數據庫
- 事務管理器:決策各個事務參與者的提交和回滾
兩階段提交:
- 準備階段:向事務管理器向事務參與者發送預備請求,事務參與者在寫本地的redo和undo日志,但是不提交,并且返回準備就緒的信息,最后提交的動作交給第二階段來進行
- 提交階段:如果事務協調者收到失敗或者超時的信息,直接給每個參與者發送回滾消息;否則提交消息,最后根據協調者的指令釋放所有事務處理過程中使用的資源鎖
二、項目例子
當前依賴,全局事務XID,不需要手動進行綁定,自動進行傳遞
<dependency>
<groupId>com.alibaba.cloud</groupId>
<!–加入spring-cloud-alibaba-seata,解決xid不傳遞問題–>
<artifactId>spring-cloud-alibaba-seata</artifactId>
<version>2.2.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
</exclusions>
</dependency>
全局事務XID需要通過過濾器或攔截器進行手動綁定,否則下游服務獲取不到全局XID回滾不了
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.3.0</version>
<!-- 這里需要排除自身的seata-all -->
<exclusions>
<exclusion>
<artifactId>seata-all</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 導入與之前下載的seata版本一致的包 -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.3.0</version>
</dependency>
OpenFeign進行手動傳遞XID
@Component
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("XID", RootContext.getXID());
}
}
提供者手動綁定XID
@Component
public class SeataFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
//手動綁定XID
String xid = request.getHeader("XID");
if(StringUtils.isNotBlank(xid)){
RootContext.bind(xid);
}
filterChain.doFilter(servletRequest,servletResponse);
}
}
seata在1.0.0版本之后就不需要手動進行數據源代理,已經被自動代理
客戶端的配置文件
seata:
enabled: true
tx-service-group: my_first_seata #配置文件中的事務服務組一樣
config:
type: nacos # nacos中拉去對應的配置文件
nacos:
server-addr: 192.168.60.46:8849
group: SEATA_GROUP
registry: # 會去nacos中拉去seata-server服務
type: nacos
nacos:
application: seata-server
server-addr: 192.168.60.46:8849
group: SEATA_GROUP
seata1.0.0之后config文件下就移除了nacos-config.txt等文件,改為了config.txt需要手動下載,并且config.txt需要在nacos-config.sh的上一級目錄下才能推送到nacos中
# 只需要修改下面幾種配置即可,這里是配置客戶端需要拉取的配置文件
service.vgroupMapping.自定義的名稱=default
store.mode=db #修改為db
store.db.dbType=mysql #修改msql的連接方式賬號和密碼
三、seata原理
1、角色劃分
-
RM:資源管理者/事務參與者,也可以是一個TM
-
TM:事務管理者,也是一個微服務,充當分布式事務的發起者
-
TC:全局事務協調者seata-server,一個包需要搭建,TC來決定事務的回滾和提交
2、AT模式
(1)核心概念
-
兩階段提交:只執行,不提交
-
seata 核心概念:邊執行,邊提交(兩階段的變種)
- 一階段:查詢前置快照---------->執行業務語句-------------->查詢出后置快照,保存只undo_log日志表中
- 二階段提交:分支插入待刪除隊列--------->異步刪除undo_log表中數據
- 二階段回滾:根據配置選項選擇是否檢驗dirty data------------>構造方向SQL----------->刪除undo_log
(2)執行流程
階段一:業務SQL:update product set name = ‘GTS’ where name = ‘TXC’
- 解析SQL,根據update product解析出update語句,表product,條件where等相關信息
- 查詢前置鏡像:根據解析sql生成查詢語句:select id, name, since from product where name = ‘TXC’
- 執行業務SQL:update product set name = ‘GTS’ where name = ‘TXC’ 更新數據
- 查詢后置鏡像:通過主鍵定位數據
- 插入回滾日志:把前后鏡像數據以及業務SQL相關的信息組成一條回滾日志記錄,插入到undo_log表中
- 提交前,向TC注冊分支,申請product表中,主鍵值記錄的全局鎖
- 本地事務提交:業務數據的更新和前面步驟中生成的undo_log一并提交
- 將本地事務的提交結果上報給TC
業務數據和回滾日志記錄會在同一個本地事務中保存,會釋放本地鎖和連接資源
階段二(回滾):
- 收到TC的分支回滾請求,開啟一個本地事務,把請求放入一個異步任務的隊列里面
- 根據XID和Branch ID查找到相應的undo_log記錄
- 數據校驗:拿undo_log中的后鏡與當前數據進行比較,如果有不同,說明當前數據被其它事務所更改,需要通過配置的策略進行處理
- 根據undo_log的前置鏡像和業務sql的相關信息組成回滾語句
- 將分支回滾的結果提交給TC
通過一階段的回滾日志進行反向補償
階段二(提交):
- 收到TC的分支提交請求,把請求放入異步隊列中,馬上返回提交成功的結果給TC
- 異步批量的刪除undo_log記錄
(3)寫隔離
一階段提交本地事務,必須需要拿到更改數據的全局鎖,拿不到全局鎖,不能提交本地事務,超出等待時間,會回滾本地事務,釋放本地鎖
例:tx1和tx2兩個全局事務同時修改 a表的m字段,m初始為1000;
tx1先開始,拿到本地鎖,將m 1000-100 = 900。本地事務提交前,先拿到該記錄的全局鎖,本地提交釋放本地鎖。tx2開始,拿到本地鎖,將m 900-100=800,提交本地事務前,先獲取該記錄的全局鎖,tx1全局事務提交前,全局鎖會被tx1所持有,tx2就會重試等待全局鎖。
tx1二階段全局提交,釋放全局鎖。tx2拿到全局鎖提交本地事務。如果tx1二階段為全局回滾,那么會重新重試獲取本地鎖,此時tx2如果還在等待全局鎖,同時持有本地鎖,tx1分支事務就會等待tx2超時釋放本地鎖之后,再次獲取本地鎖;整個過程 全局鎖都是被 tx1鎖持有,不會存在臟數據的問題
(4)讀隔離
Seata AT模式的默認全局隔離級別是讀未提交,如果在特定場景下,必需要求全局的讀已提交,Seata采用通過select for update 語句來進行代理的;select for update語句的執行會申請全局鎖 ,如果全局鎖被其它事務鎖持有,就會回滾select for update的本地執行并且重試,因為這時候查詢是被鎖住,直到全局鎖拿到,即讀取相關的數據是已提交的
3、TCC模式
AT模式是基于本地支持ACID事務的關系型數據庫:
- 一階段prepare行為:在本地事務中,一并提交數據更新和相應的回滾記錄
- 二階段commit行為:馬上成功,自動異步刪除回滾記錄
- 二階段rollback行為:通過回滾日志,自動生成補償操作,完成數據回滾
相應的TCC模式,不依賴本地底層數據的事務支持:
- 一階段prepare行為:調用自定義的prepare邏輯
- 二階段commit行為:調用自定義的commit邏輯
- 二階段rollback行為:調用自定義的rollback邏輯
4、Saga模式
- 特點:業務流程中每個參與者都提交本地事務,當某一個參與者失敗則補償前面已經成功的參與者,一階段正向服務和二階段補償服務都由業務開發者實現
- sage實現:基于狀態機引擎來實現
- 通過狀態圖來定義服務調用的流程并生成json狀態語言定義文件
- 狀態圖中一個節點可以是調用一個服務,節點可以配置它的補償節點
- 狀態圖json由狀態機引擎驅動執行,當出現異常時狀態引擎反向執行已經成功節點對應的補償節點將事務回滾(用戶可以自定義是否進行補償)
- 可以實現服務編排需求,支持單項選擇、并發、子流程、參數轉換、參數映射、服務執行狀態判斷、異常捕獲等功能
5、XA模式
- 特點:利用事務資源(數據庫、消息服務等)對 XA 協議的支持,以 XA 協議的機制來管理分支事務的一種 事務模式
原文鏈接:https://blog.csdn.net/weixin_43915643/article/details/120083982
相關推薦
- 2022-05-10 開發跨域問題的解決
- 2022-12-04 pyecharts如何旋轉折線圖的X軸標簽_python
- 2022-06-28 python反轉單鏈表算法題_python
- 2022-05-22 KVM?介紹及作用詳解_Kvm
- 2022-07-09 android開機自動啟動app的解決方法_Android
- 2022-05-24 Python?3.x踩坑實戰匯總_python
- 2023-01-29 使用Python統計代碼運行時間的兩種方法_python
- 2022-12-28 C++?Boost?Archive超詳細講解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支