JAVA 強一致性 2PC兩階段提交介紹以及Seata AT模式實現

這兩天在搞這個分佈式事務,發現網上的seata資料大多數都是樂色,啥都不是,可能他都不知道register.conf和file.conf配置是幹啥的,最後本人提供真實可用Demo,有問題可以私聊.
前一章節提過 2PC有兩種實現一種是XA,XA是傳統分佈式事務解決方案,基於數據庫必須要支持2PC協議,利用數據的2PC協議來實現分佈式事務,而一種是seata,但seata同時支持AT和TCC,這裏seata實現的AT,AT和XA執行流程一樣,都是先準備提交,最後提交還是回滾都是有事務協調器來決定,而TCC模式是在預備階段就以及提交事務,釋放鎖資源.

什麼是2PC兩階段提交

2PC即兩階段提交協議,是將整個事務流程分爲兩個階段,準備階段(Prepare phase)、提交階段(commit phase).
2是指兩個階段,P是指準備階段,C是指提交階段。

舉例:張三和李四好久不見,老友約起聚餐,飯店老闆要求先買單,才能出票。這時張三和李四分別抱怨近況不如
意,囊中羞澀,都不願意請客,這時只能AA。只有張三和李四都付款,老闆才能出票安排就餐。但由於張三和李四 都是鐵公雞,形成了尷尬的一幕:
準備階段:老闆要求張三付款,張三付款。老闆要求李四付款,李四付款。 提交階段:老闆出票,兩人拿票紛紛落座就餐。

例子中形成了一個事務,若張三或李四其中一人拒絕付款,或錢不夠,店老闆都不會給出票,並且會把已收款退 回。

整個事務過程由事務管理器和參與者組成,店老闆就是事務管理器,張三、李四就是事務參與者,事務管理器負責
決策整個分佈式事務的提交和回滾,事務參與者負責自己本地事務的提交和回滾。
在計算機中部分關係數據庫如Oracle、MySQL支持兩階段提交協議,如下圖:

  1. 準備階段(Prepare phase):事務管理器給每個參與者發送Prepare消息,每個數據庫參與者在本地執行事 務,並寫本地的Undo/Redo日誌,此時事務沒有提交。
    (Undo日誌是記錄修改前的數據,用於數據庫回滾,Redo日誌是記錄修改後的數據,用於提交事務後寫入數 據文件)
  2. 提交階段(commit phase):如果事務管理器收到了參與者的執行失敗或者超時消息時,直接給每個參與者 發送回滾(Rollback)消息;否則,發送提交(Commit)消息;參與者根據事務管理器的指令執行提交或者回滾操
    作,並釋放事務處理過程中使用的鎖資源。注意:必須在最後階段釋放鎖資源。 下圖展示了2PC的兩個階段,分成功和失敗兩個情況說明: 成功情況:

在這裏插入圖片描述

2PC主流的兩種方案XA和Seata方案

  1. XA

這裏就不講解了,傳統xa就是案例上將的
prepare階段事務沒提交,需要由事務管理器來確認事務是否提交,這樣導致傳統2PC會一直持有資源鎖,性能差

  1. Seata

是由阿里中間件團隊發起的開源項目 Fescar,後更名爲Seata,它是一個是開源的分佈式事務框架。

傳統2PC的問題在Seata中得到了解決,它通過對本地關係數據庫的分支事務的協調來驅動完成全局事務,是工作
在應用層的中間件。主要優點是性能較好,且不長時間佔用連接資源,它以高效並且對業務0侵入的方式解決微服務場景下面臨的分佈式事務問題,它目前提供AT模式(即2PC)及TCC模式的分佈式事務解決方案

Seata把一個分佈式事務理解成一個包含了若干分支事務的全局事務。全局事務的職責是協調其下管轄的分支事務
達成一致,要麼一起成功提交,要麼一起失敗回滾。此外,通常分支事務本身就是一個關係數據庫的本地事務,下 圖是全局事務與分支事務的關係圖:

在這裏插入圖片描述

Seata實現2PC與傳統2PC的差別: 架構層次方面,傳統2PC方案的 RM 實際上是在數據庫層,RM 本質上就是數據庫自身,通過 XA協議實現,而 Seata的 RM 是以jar包的形式作爲中間件層部署在應用程序這一側的。
兩階段提交方面,傳統2PC無論第二階段的決議是commit還是rollback,事務性資源的鎖都要保持到Phase2完成
才釋放。而Seata的做法是在Phase1 就將本地事務提交,這樣就可以省去Phase2持鎖的時間,整體提高效率。

seata實現AT事務

本示例通過Seata中間件實現分佈式事務,模擬三個賬戶的轉賬交易過程。
兩個賬戶在三個不同的銀行(張三在bank1、李四在bank2),bank1和bank2是兩個個微服務。交易過程是,張三 給李四轉賬指定金額。

上述交易步驟,要麼一起成功,要麼一起失敗,必須是一個整體性的事務。
在這裏插入圖片描述

交互流程如下: 1、請求bank1進行轉賬,傳入轉賬金額。 2、bank1減少轉賬金額,調用bank2,傳入轉賬金額。

  1. 首先要下載事務協調器: https://github.com/seata/seata/releases/download/v0.7.1/seata-server-0.7.1.zip

  2. 解壓啓動: seata-server.bat -p 8888 -m file

    注:其中8888爲服務端口號;file爲啓動模式,這裏指seata服務將採用文件的方式存儲信息。
    在這裏插入圖片描述
    如上圖出現“Server started…”的字樣則表示啓動成功。

  3. 創建mysql

兩個庫 bank1和bank2 都創建account_info 和undo_log表

CREATE TABLE `account_info` (
  `id` bigint(20) DEFAULT NULL COMMENT 'id',
  `account_name` varchar(100) DEFAULT NULL COMMENT '戶主姓名',
  `account_no` varchar(100) DEFAULT NULL COMMENT '戶主id',
  `account_password` varchar(100) DEFAULT NULL COMMENT '帳戶密碼',
  `account_balance` double DEFAULT NULL COMMENT '帳戶餘額'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='賬戶表'
CREATE TABLE `undo_log` (
  `id` bigint(20) DEFAULT NULL COMMENT 'id',
  `branch_id` varchar(100) DEFAULT NULL COMMENT '分支id',
  `xid` varchar(100) DEFAULT NULL COMMENT '事務id',
  `context` varchar(100) DEFAULT NULL COMMENT '內容',
  `rollback_info` double DEFAULT NULL COMMENT '回滾信息',
  `log_status` double DEFAULT NULL COMMENT '日誌狀態',
  `log_created` double DEFAULT NULL COMMENT '日誌創建',
  `log_modified` double DEFAULT NULL COMMENT '日誌修改',
  `ext` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='undo log表'
注意 undo_log名稱以及字段不可修改,這個是seata 的undo日誌,在上面流程中提過,Undo日誌是記錄修改前的數據,用於數據庫回滾,Redo日誌是記錄修改後的數據,用於提交事務後寫入數 據文件
  1. 創建SpringCloud工程,我這裏使用spring全家桶,你也可以用阿里cloud全家桶
    我這裏使用SpringCloud最新版 Hoxton.SR5 SpringBoot使用2.3.1.RELEASE

這裏就提示以下代碼的作用以及關鍵處如何配置,源代碼地址: https://github.com/cyf0477/seata-parent

說明一下注冊中心還是Eureka的註冊中心,沒有任何改變

在這裏插入圖片描述
1.在bank1和bank2裏分別加入seata依賴
2.在resource下加入registry.conf,這個conf需要在之前下載的seata服務器資源裏的conf目錄下copy

在這裏插入圖片描述
這裏面需要關注兩個文件,一個是register.conf,一個是file.conf ,這裏就先講講這個register.conf和file.conf的作用,

  1. register.conf: 用於配置seata負載均衡方式,seata是分佈式事務協調器,既然是分佈式那麼要實現高可用,必然需要有註冊中心,下面就是默認register.conf內容,裏面加有詳細註釋

		registry {
		  #註冊中心選用的方式,默認是file,可以使用nacos ,eureka上面註釋列舉的所有方式都支持
		  #注意,如果這裏註冊中心原則使用file方式,那麼就必須使用file.conf來配置file的一些配置,而且file模式不支持高可用
		  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
		  type = "file"  只能建立一個seata server
		
		  nacos {
		    serverAddr = "localhost"
		    namespace = "public"
		    cluster = "default"
		  }
		  eureka {
		    serviceUrl = "http://localhost:1001/eureka"    #這裏我用的eureka,那麼只需要修改eureka就可以
		    application = "default"   #seata註冊到eureka的名稱
		    weight = "1"    #權重
		  }
		  redis {
		    serverAddr = "localhost:6379"
		    db = "0"
		  }
		  zk {
		    cluster = "default"
		    serverAddr = "127.0.0.1:2181"
		    session.timeout = 6000
		    connect.timeout = 2000
		  }
		  consul {
		    cluster = "default"
		    serverAddr = "127.0.0.1:8500"
		  }
		  etcd3 {
		    cluster = "default"
		    serverAddr = "http://localhost:2379"
		  }
		  sofa {
		    serverAddr = "127.0.0.1:9603"
		    application = "default"
		    region = "DEFAULT_ZONE"
		    datacenter = "DefaultDataCenter"
		    cluster = "default"
		    group = "SEATA_GROUP"
		    addressWaitTime = "3000"
		  }
		  file {
		    name = "file.conf"
		  }
		}
		
		config {     //conf只有下面列舉的才需要修改   如果使用的eureka  下面配置無用
		  # file、nacos 、apollo、zk、consul、etcd3
		  type = "file"
		
		  nacos {
		    serverAddr = "localhost"
		    namespace = "public"
		    cluster = "default"
		  }
		  consul {
		    serverAddr = "127.0.0.1:8500"
		  }
		  apollo {
		    app.id = "seata-server"
		    apollo.meta = "http://192.168.1.204:8801"
		  }
		  zk {
		    serverAddr = "127.0.0.1:2181"
		    session.timeout = 6000
		    connect.timeout = 2000
		  }
		  etcd3 {
		    serverAddr = "http://localhost:2379"
		  }
		  file {
		    name = "file.conf"
		  }
		}
  1. file.conf: seata 註冊中心指定爲file file.conf纔有意義,並且如果指定爲file 類型,那麼seata不支持高可用!,這裏就不講解file.conf裏面的內容了,畢竟沒一點意義
  2. 修改yml配置
spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: my_test_tx_group   #seata分組
seata:
  service:
    grouplist:
      default: ubuntu1804.wsl:8091  #seata服務地址  可以是多個  key的值我查看源碼裏沒有要求指定什麼名字,這裏就隨意了,如果seata集羣,可以寫多個服務地址

bank1 代表案例中的張三,先說一下數據源配置,讓seata代理數據源,io.seata.rm.datasource.DataSourceProxy,這樣seata纔可能完全管理事務狀態
在這裏插入圖片描述

需要在主事物分支開啓@GlobalTransactional註解,在其他子事物分子是不需要這個註解

張三service
在這裏插入圖片描述
李四service

在這裏插入圖片描述

此時 seata at教程就完畢了 到這裏有人可能有點混淆AT和XA AT是在seata裏的概念等同於XA 都是兩階段提交解決方案 tcc解決方案使用hmily下章節講解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章