在微服務架構下,雖然咱們會盡可能避免分佈式事務,可是隻要業務複雜的狀況下這是一個繞不開的問題,如何保證業務數據一致性呢?本文主要介紹同步場景下使用Seata
的AT模式
來解決一致性問題。java
Seata
是
阿里巴巴 開源的
一站式分佈式事務解決方案 中間件,以
高效 而且對業務
0 侵入 的方式,解決
微服務 場景下面臨的分佈式事務問題
總體事務邏輯是基於 兩階段提交 的模型,核心概念包括如下3個角色:git
目前的Seata
有兩種模式可以使用分別對應不一樣業務場景github
該模式適合的場景:spring
ACID
事務的關係型數據庫。JDBC
訪問數據庫。
一個典型的分佈式事務過程:sql
TM
向 TC
申請開啓一個全局事務,全局事務建立成功並生成一個全局惟一的 XID
。XID
在微服務調用鏈路的上下文中傳播。RM
向 TC
註冊分支事務,將其歸入 XID 對應全局事務的管轄。TM
向 TC
發起針對 XID
的全局提交或回滾決議。TC
調度 XID
下管轄的所有分支事務完成提交或回滾請求。
該模式邏輯相似TCC
,須要 自定義實現 prepare
、commit
和rollback
的邏輯,適合 非關係型數據庫 的場景數據庫
模擬一個簡單的用戶下單場景,4個子工程分別是 Bussiness(事務發起者)、Order(建立訂單)、Storage(扣減庫存) 和 Account(扣減帳戶餘額)json
Discover
註冊、Config
配置和Store
存儲模塊默認都是使用file
只能適用於單機,咱們安裝的時候分別改爲使用nacos
和Mysql
以支持server端集羣bootstrap
https://github.com/seata/seat...segmentfault
註冊中心和配置中心默認是file
這裏改成nacos
;設置 registry 和 config 節點中的type
爲nacos
,修改serverAddr
爲你的nacos
節點地址。bash
registry { type = "nacos" nacos { serverAddr = "192.168.28.130" namespace = "public" cluster = "default" } } config { type = "nacos" nacos { serverAddr = "192.168.28.130" namespace = "public" cluster = "default" } }
默認組名爲${spring.application.name}-fescar-service-group
,可經過spring.cloud.alibaba.seata.tx-service-group
配置修改
db
,並修改數據庫相關配置
cd conf sh nacos-config.sh 192.168.28.130
成功後在nacos
的配置列表中能看到seata
的相關配置
執行conf/db_store.sql
中的腳本
sh bin/seata-server.sh -p 8091 -h 192.168.28.130
執行腳本 seata-demo.sql
需在業務相關的數據庫中添加 undo_log 表,用於保存須要回滾的數據
直接把 seata-server 中的registry.conf
複製到每一個服務中去便可,不須要修改
demo中的每一個服務各自修改配置文件
Seata
是經過代理數據源實現分佈式事務,因此須要配置io.seata.rm.datasource.DataSourceProxy
的Bean
,且是@Primary
默認的數據源,不然事務不會回滾,沒法實現分佈式事務
public class DataSourceProxyConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DruidDataSource druidDataSource() { return new DruidDataSource(); } @Primary @Bean public DataSourceProxy dataSourceProxy(DruidDataSource druidDataSource) { return new DataSourceProxy(druidDataSource); } }
由於使用了mybatis的starter因此須要排除DataSourceAutoConfiguration
,否則會產生循環依賴
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
事務發起者 business-service
添加 @GlobalTransactional
註解
@GlobalTransactional public void placeOrder(String userId) { ...... }
提供兩個接口測試
http://localhost:9090/placeOrder
http://localhost:9090/placeOrderFallBack
https://gitee.com/zlt2000/microservices-platform/tree/master/zlt-demo/seata-demo
推薦閱讀
掃碼關注有驚喜!