架构设计 | 基于Seata中间件,微服务模式下事务管理
源碼地址:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里
一、Seata簡介
1、Seata組件
Seata是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡單易用的分布式事務(wù)服務(wù)。Seata將為用戶提供了AT、TCC、SAGA、XA事務(wù)模式,為用戶打造一站式的分布式解決方案。
2、支持模式
AT 模式
- 基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫。
- Java應(yīng)用,通過 JDBC 訪問數(shù)據(jù)庫。
一階段:業(yè)務(wù)數(shù)據(jù)和回滾日志記錄在同一個(gè)本地事務(wù)中提交,釋放本地鎖和連接資源。
二階段:提交異步化,非??焖俚赝瓿?。回滾通過一階段的回滾日志進(jìn)行反向補(bǔ)償。
TCC模式
一個(gè)分布式的全局事務(wù),整體是兩階段提交的模型,全局事務(wù)是由若干分支事務(wù)組成的,分支事務(wù)要滿足兩階段提交的模型要求,即需要每個(gè)分支事務(wù)都具備自己的:
一階段 prepare 行為
二階段 commit 或 rollback 行為
Saga模式
Saga模式是SEATA提供的長事務(wù)解決方案,在Saga模式中,業(yè)務(wù)流程中每個(gè)參與者都提交本地事務(wù),當(dāng)出現(xiàn)某一個(gè)參與者失敗則補(bǔ)償前面已經(jīng)成功的參與者,一階段正向服務(wù)和二階段補(bǔ)償服務(wù)都由業(yè)務(wù)開發(fā)實(shí)現(xiàn)。
XA模式
XA是一個(gè)分布式事務(wù)協(xié)議,對業(yè)務(wù)無侵入的分布式事務(wù)解決方案,XA提交協(xié)議需要事務(wù)參與者的數(shù)據(jù)庫支持,XA事務(wù)具有強(qiáng)一致性,在兩階段提交的整個(gè)過程中,一直會持有資源的鎖,性能不理想的缺點(diǎn)很明顯。
二、服務(wù)端部署
1、下載組件包
1.2版本:seata-server-1.2.0.zip
解壓目錄
- bin:存放服務(wù)端運(yùn)行啟動(dòng)腳本;
- lib:存放服務(wù)端依賴的資源jar包;
- conf:配置文件目錄。
2、修改配置
file.conf配置
mode:db 即使用數(shù)據(jù)庫存儲事務(wù)信息,這里還可以選擇file存儲方式。
file模式為單機(jī)模式,全局事務(wù)會話信息內(nèi)存中讀寫并持久化本地文件root.data,性能較高;
db模式為高可用模式,全局事務(wù)會話信息通過db共享,相應(yīng)性能差些;
redis模式Seata-Server 1.3及以上版本支持,性能較高,存在事務(wù)信息丟失風(fēng)險(xiǎn),請?zhí)崆芭渲煤线m當(dāng)前場景的redis持久化配置.
store {## store mode: file、dbmode = "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 = 5maxConn = 30globalTable = "global_table"branchTable = "branch_table"lockTable = "lock_table"queryLimit = 100maxWait = 5000} }registry.conf配置
這里選擇eureka作為注冊中心,seata-server也要作為一個(gè)服務(wù)添加到注冊中心,不使用配置中心所以config配置默認(rèn)即可。
registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "eureka"eureka {serviceUrl = "http://localhost:8761/eureka"application = "default"weight = "1"} }3、事務(wù)管理表
需要在seata-server即上述配置的MySQL庫中建立3張事務(wù)管理表:
- 全局事務(wù):global_table
- 分支事務(wù):branch_table
- 全局鎖:lock_table
- 事務(wù)回滾:undo_log
- SQL腳本:mysql-script目錄
4、啟動(dòng)命令
Linux環(huán)境:sh seata-server.sh
三、業(yè)務(wù)服務(wù)搭建
1、代碼結(jié)構(gòu)
- seata-eureka:注冊中心
- seata-order:訂單服務(wù)
- seata-account:賬戶服務(wù)
- seata-inventor:庫存服務(wù)
- seata-client:客戶端服務(wù)
- account-feign:賬戶Feign接口
- inventory-feign:庫存Feign接口
- order-feign:訂單Feign接口
請求鏈路:客戶端->訂單->賬戶+庫存,測試整個(gè)流程的分布式事務(wù)問題。
2、數(shù)據(jù)庫結(jié)構(gòu)
- seata_server:seata組件服務(wù)端依賴庫
- seata_account:模擬賬戶數(shù)據(jù)庫
- seata_inventor:模擬庫存數(shù)據(jù)庫
- seata_order:模擬訂單數(shù)據(jù)庫
各個(gè)庫腳本位置:mysql-script/data-biz.sql
3、啟動(dòng)服務(wù)
依次啟動(dòng):注冊中心,庫存服務(wù),賬戶服務(wù),訂單服務(wù),客戶端服務(wù);
Eureka服務(wù)列表如下:
四、Seata用法詳解
1、Seata基礎(chǔ)配置
幾個(gè)基礎(chǔ)服務(wù)的配置方式一樣。
conf配置
file.conf重點(diǎn)關(guān)注下面內(nèi)容,事務(wù)組的名稱,需要在yml文件中使用。
my_test_tx_group = "default"registry.conf:是注冊中心的選擇。
2、數(shù)據(jù)庫配置
注意這里的事務(wù)組名稱配置。
spring:# 事務(wù)組的名稱cloud:alibaba:seata:tx-service-group: my_test_tx_group# 數(shù)據(jù)源配置datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:driverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/seata_accountusername: rootpassword: 123456將數(shù)據(jù)庫整體由Seata進(jìn)行代理管理,核心API:DataSourceProxy。
@Configuration public class SeataAccountConfig {@Value("${spring.application.name}")private String applicationName;@Beanpublic 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);}@Beanpublic 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、業(yè)務(wù)代碼
核心注解:GlobalTransactional,管理整體的分布式事務(wù)。
@Service public class OrderServiceImpl implements OrderService {private final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);@Resourceprivate OrderMapper orderMapper ;@Resourceprivate AccountFeign accountFeign ;@Resourceprivate InventoryFeign inventoryFeign ;@GlobalTransactional@Overridepublic Integer createOrder(String orderNo) {LOGGER.info("Order 生成中 "+orderNo);// 本服務(wù)下訂單庫Integer insertFlag = orderMapper.insert(orderNo) ;// 基于feign接口處理賬戶和庫存accountFeign.updateAccount(10L) ;inventoryFeign.updateInventory(10) ;return insertFlag ;} }測試流程:在任意服務(wù)下拋出異常,觀察整體的事務(wù)狀態(tài),觀察是否有整體的事務(wù)控制效果。
五、源代碼地址
GitHub地址:知了一笑 https://github.com/cicadasmile/spring-cloud-base GitEE地址:知了一笑 https://gitee.com/cicadasmile/spring-cloud-base推薦閱讀:架構(gòu)設(shè)計(jì)系列
| 架構(gòu)設(shè)計(jì):單服務(wù).集群.分布式,基本區(qū)別和聯(lián)系 |
| 架構(gòu)設(shè)計(jì):分布式業(yè)務(wù)系統(tǒng)中,全局ID生成策略 |
| 架構(gòu)設(shè)計(jì):分布式系統(tǒng)調(diào)度,Zookeeper集群化管理 |
| 架構(gòu)設(shè)計(jì):接口冪等性原則,防重復(fù)提交Token管理 |
| 架構(gòu)設(shè)計(jì):緩存管理模式,監(jiān)控和內(nèi)存回收策略 |
| 架構(gòu)設(shè)計(jì):異步處理流程,多種實(shí)現(xiàn)模式詳解 |
| 架構(gòu)設(shè)計(jì):高并發(fā)流量削峰,共享資源加鎖機(jī)制 |
| 架構(gòu)設(shè)計(jì):分布式服務(wù),庫表拆分模式詳解 |
| 架構(gòu)設(shè)計(jì):分布式事務(wù)①概念簡介和基礎(chǔ)理論 |
| 架構(gòu)設(shè)計(jì):基于電商交易流程,圖解TCC事務(wù)分段提交 |
| 架構(gòu)設(shè)計(jì):基于消息中間件,圖解柔性事務(wù)一致性 |
總結(jié)
以上是生活随笔為你收集整理的架构设计 | 基于Seata中间件,微服务模式下事务管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 专刊文章 - Web UI框架引领J2E
- 下一篇: maven中的snapshot来源与注意