一、什么是Seata?
Seata是一款開源的分布式事務解決方案,致力於提供高性能和簡單易用的分布式事務服務。Seata將為用戶提供了AT、TCC、SAGA 和XA事務模式,為用戶打造一站式的分布式解決方案。
微服務中通常一次大的操作由不同的小操作組成的,這些小的操作分布在不同的服務器上,我們需要一定的方案來保證這些小操作要么全部成功,要么全部失敗。從本質上來說,就是為了保證不同數據庫的數據一致性。分布式事務就是一個保證數據一致性的解決方案。
Seata分布式事務的處理包含全局唯一事務ID和三個組件模塊TC\TM\RM:
TC事務協調器:維護全局事務的運行狀態,負責協調並驅動全局事務的提交或回滾。
TM事務管理器:控制全局事務的邊界,負責開啟一個全局事務,並最終發起全局提交或全局回滾的決議。
RM資源管理器:控制分支事務,負責分支注冊,狀態匯報,並接收事務協調器的指令,驅動分支事務的提交和回滾。
以下是分布式事務的處理過程:
1. TM向TC申請開啟一個全局事務,全局事務創建成功並生成一個全局唯一的XID。
2. XID在微服務調用鏈路的上下文中傳播。
3. RM向TC注冊分支事務,將其納入XID對應全局事務的管轄。
4.TM向TC發起針對XID的全局提交或回滾決議。
5.TC調度XID下管轄的全部分支事務完成提交或回滾請求。
二、Seata的使用
1、下載安裝:去http://seata.io/zh-cn下載對應版本,解壓到指定目錄並修改conf目錄下的file.conf配置文件。主要配置自定義事務組的名稱,事務日志的存儲模式為db和數據庫連接信息。
a. 修改自定義事務組名稱:service.vgroup_mapping.my_test_tx_grou= "zqh_tx_group" 。
b.修改事務日志的存儲模式:store.mode="db"。
c.創建數據庫,復制conf/db_store.sql代碼去庫下執行創建表。
d.配置數據連接:db.*下配置。
e.修改conf/registry.conf文件:設置registry.type="nacos", nacos{ serverAddr="localhost:8848",namsespace="" ,cluster=“default”},將Seata-server服務注冊到nacos注冊中心。
f.啟動:先啟動nacos、后啟動seata(運行bin/seata-server.bat)。
2、創建微服務對應的業務數據庫:每個微服務需要對應一個數據庫,為每個微服務的數據庫創建各自的回滾日志表:復制conf/db_undo_log.sql在每個庫中執行一次。
3、創建微服務(Controller-domain-Dao-Service-mapping代碼結構):
a.引入seata包,要注意排除jar包沖突:
<! --seata-->
<dependency>
<grouprd>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<artifactid>seata-all</artifactId>
<groupid>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupid>io.seata</grouprd>
<artifactId>seata-all</artifactId>
<version>0.9.0</version>
</dependency>
b.配置yml文件,指定事務組名稱:
server: port: 2001 spring: application: name: seata-order-service cloud: alibaba: seata: #自定義事務組名稱需要與seata-server中的對應 tx-service-group: zqh_tx_group nacos: discovery: server-addr: localhost:8848 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc :mysql:/ /localhost:3306/ seata_order username: root password: 123456
c.復制file.conf、registry.conf到微服務resources資源文件夾。
d.主啟動類增加@SpringBootApplication(exclude = DatasourceAutoconfiguration.class)注解取消數據源的自動創建,選擇使用自定義的Seata數據源DataSourceProxyConfig類進行代理。
e.在調用微服務的接口服務類上增加@GlobalTransactional注解,完成微服務的一些列調用過程中的事務處理,當調用微服務過程中出現rollbackFor指定的異常,就會全局回滾create()里的任何調用,例如
/*創建訂單->調用庫存服務扣減庫存->調用賬戶服務扣減賬戶余額->修改訂單狀態*簡單說:下訂單->扣庫存->減余額->改狀態*/ @override @GlobalTransactional(name = "zqh-create-order" ,rollbackFor = Exception.class) //rollbackFor表示導致事務回滾的異常類數組,name表示事務的名稱,具有唯一性 public void create(order order) { Log.info("----->開始新建訂單"); orderDao.create(order); Log.info("----->訂單微服務開始調用庫存,做扣減count" ); storageservice.decrease(order.getProductId() ,order.getcount()); Log.info("----->訂單微服務開始調用賬戶,做扣減Money" ) ; accountservice.decrease(order.getuserId( ) ,order.getMoney()); Log.info("----->訂單微服務開始修改訂單狀態"); orderDao.update(order-getuserId(), status: 1); Log.info( "----->修改訂單狀態結束"); Log.info("----->下訂單結束了,o(n_n)o哈哈~"); }
三、Seata原理簡介
Seata是2019年螞蟻金服和阿里巴巴共同開源的分布式事務解決方案,商用的時候要使用1.0以上,0.9版本不支持大規模集群。在前面我們完成了簡單的微服務事務方案,其中增加了@GlobalTransactional注解的微服務就是TM,Seata服務器就是TC,事務的參與方就是RM。
在運行第一階段,Seata會攔截業務sql語句,解析sql語義,在數據操作前保存之前的"before image"鏡像,執行操作后保存"after image"鏡像,最后生成行鎖,這些操作全部在一個事務中完成。流程如下:
第二階段,如果提交順利,Seata會將第一階段保存的快照數據和行鎖刪除清空數據即可,反之則根據快照恢復全部數據到之前的狀態(在還原數據之前會校驗臟寫,檢查是否已被其他操作處理過,如果是則需要人工介入),然后再刪除快照和行鎖數據。流程如下: