1. 程式人生 > >架構設計 | 基於Seata中介軟體,微服務模式下事務管理

架構設計 | 基於Seata中介軟體,微服務模式下事務管理

原始碼地址:[GitHub·點這裡](https://github.com/cicadasmile/spring-cloud-base) || [GitEE·點這裡](https://gitee.com/cicadasmile/spring-cloud-base) # 一、Seata簡介 ## 1、Seata元件 Seata是一款開源的分散式事務解決方案,致力於提供高效能和簡單易用的分散式事務服務。Seata將為使用者提供了AT、TCC、SAGA、XA事務模式,為使用者打造一站式的分散式解決方案。 ## 2、支援模式 **AT 模式** - 基於支援本地 ACID 事務的關係型資料庫。 - Java應用,通過 JDBC 訪問資料庫。 一階段:業務資料和回滾日誌記錄在同一個本地事務中提交,釋放本地鎖和連線資源。 二階段:提交非同步化,非常快速地完成。回滾通過一階段的回滾日誌進行反向補償。 **TCC模式** 一個分散式的全域性事務,整體是兩階段提交的模型,全域性事務是由若干分支事務組成的,分支事務要滿足兩階段提交的模型要求,即需要每個分支事務都具備自己的: 一階段 prepare 行為 二階段 commit 或 rollback 行為 **Saga模式** Saga模式是SEATA提供的長事務解決方案,在Saga模式中,業務流程中每個參與者都提交本地事務,當出現某一個參與者失敗則補償前面已經成功的參與者,一階段正向服務和二階段補償服務都由業務開發實現。 **XA模式** XA是一個分散式事務協議,對業務無侵入的分散式事務解決方案,XA提交協議需要事務參與者的資料庫支援,XA事務具有強一致性,在兩階段提交的整個過程中,一直會持有資源的鎖,效能不理想的缺點很明顯。 # 二、服務端部署 ## 1、下載元件包 1.2版本:seata-server-1.2.0.zip 解壓目錄 - bin:存放服務端執行啟動指令碼; - lib:存放服務端依賴的資源jar包; - conf:配置檔案目錄。 ## 2、修改配置 **file.conf配置** mode:db 即使用資料庫儲存事務資訊,這裡還可以選擇file儲存方式。 file模式為單機模式,全域性事務會話資訊記憶體中讀寫並持久化本地檔案root.data,效能較高; db模式為高可用模式,全域性事務會話資訊通過db共享,相應效能差些; redis模式Seata-Server 1.3及以上版本支援,效能較高,存在事務資訊丟失風險,請提前配置合適當前場景的redis持久化配置. ``` store { ## store mode: file、db mode = "db" db { datasource = "druid" dbType = "mysql" driverClassName = "com.mysql.jdbc.Driver" url = "jdbc:mysql://127.0.0.1:3306/seata_server" user = "root" password = "123456" minConn = 5 maxConn = 30 globalTable = "global_table" branchTable = "branch_table" lockTable = "lock_table" queryLimit = 100 maxWait = 5000 } } ``` **registry.conf配置** 這裡選擇eureka作為註冊中心,seata-server也要作為一個服務新增到註冊中心,不使用配置中心所以config配置預設即可。 ``` registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "eureka" eureka { serviceUrl = "http://localhost:8761/eureka" application = "default" weight = "1" } } ``` ## 3、事務管理表 需要在seata-server即上述配置的MySQL庫中建立3張事務管理表: - 全域性事務:global_table - 分支事務:branch_table - 全域性鎖:lock_table - 事務回滾:undo_log - SQL指令碼:mysql-script目錄 ## 4、啟動命令 Linux環境:sh seata-server.sh # 三、業務服務搭建 ## 1、程式碼結構 ![](https://img2020.cnblogs.com/blog/1691717/202009/1691717-20200914160032295-656581985.png) - seata-eureka:註冊中心 - seata-order:訂單服務 - seata-account:賬戶服務 - seata-inventor:庫存服務 - seata-client:客戶端服務 - account-feign:賬戶Feign介面 - inventory-feign:庫存Feign介面 - order-feign:訂單Feign介面 **請求鏈路**:客戶端->訂單->賬戶+庫存,測試整個流程的分散式事務問題。 ## 2、資料庫結構 ![](https://img2020.cnblogs.com/blog/1691717/202009/1691717-20200914160046319-2103366742.png) - seata_server:seata元件服務端依賴庫 - seata_account:模擬賬戶資料庫 - seata_inventor:模擬庫存資料庫 - seata_order:模擬訂單資料庫 各個庫指令碼位置:mysql-script/data-biz.sql ## 3、啟動服務 依次啟動:註冊中心,庫存服務,賬戶服務,訂單服務,客戶端服務; Eureka服務列表如下: ![](https://img2020.cnblogs.com/blog/1691717/202009/1691717-20200914160059521-1504437819.png) # 四、Seata用法詳解 ## 1、Seata基礎配置 ![](https://img2020.cnblogs.com/blog/1691717/202009/1691717-20200914160111585-1413613140.png) 幾個基礎服務的配置方式一樣。 **conf配置** file.conf重點關注下面內容,事務組的名稱,需要在yml檔案中使用。 ``` my_test_tx_group = "default" ``` **registry.conf**:是註冊中心的選擇。 ## 2、資料庫配置 注意這裡的事務組名稱配置。 ``` spring: # 事務組的名稱 cloud: alibaba: seata: tx-service-group: my_test_tx_group # 資料來源配置 datasource: type: com.alibaba.druid.pool.DruidDataSource druid: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/seata_account username: root password: 123456 ``` 將資料庫整體由Seata進行代理管理,核心API:DataSourceProxy。 ```java @Configuration public class SeataAccountConfig { @Value("${spring.application.name}") private String applicationName; @Bean public GlobalTransactionScanner globalTransactionScanner() { return new GlobalTransactionScanner(applicationName, "test-tx-group"); } @Bean @ConfigurationProperties(prefix = "spring.datasource.druid") public DruidDataSource druidDataSource() { return new DruidDataSource() ; } @Primary @Bean("dataSource") public DataSourceProxy dataSourceProxy(DataSource druidDataSource) { return new DataSourceProxy(druidDataSource); } @Bean public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy)throws Exception{ SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSourceProxy); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath*:/mapper/*.xml")); sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory()); return sqlSessionFactoryBean.getObject(); } } ``` ## 3、業務程式碼 核心註解:GlobalTransactional,管理整體的分散式事務。 ``` @Service public class OrderServiceImpl implements OrderService { private final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class); @Resource private OrderMapper orderMapper ; @Resource private AccountFeign accountFeign ; @Resource private InventoryFeign inventoryFeign ; @GlobalTransactional @Override public Integer createOrder(String orderNo) { LOGGER.info("Order 生成中 "+orderNo); // 本服務下訂單庫 Integer insertFlag = orderMapper.insert(orderNo) ; // 基於feign介面處理賬戶和庫存 accountFeign.updateAccount(10L) ; inventoryFeign.updateInventory(10) ; return insertFlag ; } } ``` 測試流程:在任意服務下丟擲異常,觀察整體的事務狀態,觀察是否有整體的事務控制效果。 # 五、原始碼地址 ``` GitHub地址:知了一笑 https://github.com/cicadasmile/spring-cloud-base GitEE地址:知了一笑 https://gitee.com/cicadasmile/spring-cloud-base ``` **推薦閱讀:架構設計系列** | 標題| |:---| | [架構設計:單服務.叢集.分散式,基本區別和聯絡](https://mp.weixin.qq.com/s/NGxI3rC-6mWMDnrClaOR3Q)| | [架構設計:分散式業務系統中,全域性ID生成策略](https://mp.weixin.qq.com/s/1TKAwr99rKEHSxqXFixEhQ)| | [架構設計:分散式系統排程,Zookeeper叢集化管理](https://mp.weixin.qq.com/s/Yr4A95poVjlFsQ-Q0dF7hA)| | [架構設計:介面冪等性原則,防重複提交Token管理](https://mp.weixin.qq.com/s/o9sxN6GwxdNYTKZvRexwjg)| | [架構設計:快取管理模式,監控和記憶體回收策略](https://mp.weixin.qq.com/s/jBu-OZ69DbXfmdIf5VC7kQ)| | [架構設計:非同步處理流程,多種實現模式詳解](https://mp.weixin.qq.com/s/RQm1vPJak0rCGW8dll4oAA)| | [架構設計:高併發流量削峰,共享資源加鎖機制](https://mp.weixin.qq.com/s/T13aak6us7ZF36qooQ-YPQ)| | [架構設計:分散式服務,庫表拆分模式詳解](https://mp.weixin.qq.com/s/EZCIgZ4EWvFKgKlCYej68g)| | [架構設計:分散式事務①概念簡介和基礎理論](https://mp.weixin.qq.com/s/7ppTArAcu_i8ENa-tNo76A)| | [架構設計:基於電商交易流程,圖解TCC事務分段提交](https://mp.weixin.qq.com/s/-vevjP5z2BMnrKn-8cYY7Q)| | [架構設計:基於訊息中介軟體,圖解柔性事務一致性](https://mp.weixin.qq.com/s/T6NVFeHxp1h2OXsjA