seata使用
原文
本文只介紹Seata的簡單使用,沒有涉及其原理.
1.在本地搭建一個TC服務(wù)(事務(wù)協(xié)調(diào)者).
1.1 下載seata的安裝包
官網(wǎng)(https://github.com/seata/seata/releases)
往下滑滑,找到你想要的版本和格式下載即可.我這里使用的是seata-server-1.1.0.zip,解壓即可使用.
1.2 配置
打開解壓目錄下的conf/registry.conf文件如下
所以接下來看一下file.conf文件
## transaction log store, only used in seata-server store {## store mode: file、db#選擇配置中心的存儲模式,由于選擇file存到文件里(性能高)會變?yōu)槎M(jìn)制流不好觀察,所以選擇數(shù)據(jù)庫#復(fù)制之后一定要改一改mode = "db"## file store propertyfile {## store location dirdir = "sessionStore"# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptionsmaxBranchSessionSize = 16384# globe session size , if exceeded throws exceptionsmaxGlobalSessionSize = 512# file buffer size , if exceeded allocate new bufferfileWriteBufferCacheSize = 16384# when recover batch read sizesessionReloadReadSize = 100# async, syncflushDiskMode = async}## database store propertydb {#選擇了數(shù)據(jù)庫必定要做出一些配置,數(shù)據(jù)庫里一定要有這3張表## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.datasource = "dbcp"## mysql/oracle/h2/oceanbase etc.dbType = "mysql"driverClassName = "com.mysql.jdbc.Driver"url = "jdbc:mysql://192.168.206.99:3306/seata"user = "root"password = "root"minConn = 1maxConn = 10globalTable = "global_table"branchTable = "branch_table"lockTable = "lock_table"queryLimit = 100} }建表SQL如下:
CREATE TABLE IF NOT EXISTS `global_table` (`xid` VARCHAR(128) NOT NULL,`transaction_id` BIGINT,`status` TINYINT NOT NULL,`application_id` VARCHAR(32),`transaction_service_group` VARCHAR(32),`transaction_name` VARCHAR(128),`timeout` INT,`begin_time` BIGINT,`application_data` VARCHAR(2000),`gmt_create` DATETIME,`gmt_modified` DATETIME,PRIMARY KEY (`xid`),KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),KEY `idx_transaction_id` (`transaction_id`) ) ENGINE = InnoDBDEFAULT CHARSET = utf8;-- the table to store BranchSession data CREATE TABLE IF NOT EXISTS `branch_table` (`branch_id` BIGINT NOT NULL,`xid` VARCHAR(128) NOT NULL,`transaction_id` BIGINT,`resource_group_id` VARCHAR(32),`resource_id` VARCHAR(256),`branch_type` VARCHAR(8),`status` TINYINT,`client_id` VARCHAR(64),`application_data` VARCHAR(2000),`gmt_create` DATETIME,`gmt_modified` DATETIME,PRIMARY KEY (`branch_id`),KEY `idx_xid` (`xid`) ) ENGINE = InnoDBDEFAULT CHARSET = utf8;-- the table to store lock data CREATE TABLE IF NOT EXISTS `lock_table` (`row_key` VARCHAR(128) NOT NULL,`xid` VARCHAR(96),`transaction_id` BIGINT,`branch_id` BIGINT NOT NULL,`resource_id` VARCHAR(256),`table_name` VARCHAR(32),`pk` VARCHAR(36),`gmt_create` DATETIME,`gmt_modified` DATETIME,PRIMARY KEY (`row_key`),KEY `idx_branch_id` (`branch_id`) ) ENGINE = InnoDBDEFAULT CHARSET = utf8;1.3 啟動
如果是linux環(huán)境(要有JRE),執(zhí)行seata-server.sh
如果是windows環(huán)境,執(zhí)行seata-server.bat
2 改造微服務(wù)
只要是需要用到seata(分布式事務(wù))的服務(wù),都要做類似的配置.
2.1 引入依賴
我這里是springboot項目,所以我先在父pom中聲明了.如下
接下來只要在需要seata的微服務(wù)里添加依賴就好了.
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-seata</artifactId> </dependency> <dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId> </dependency>2.2 添加配置
spring:cloud:alibaba:seata:tx-service-group: test_tx_group # 定義事務(wù)組的名稱2.3 在resources目錄下添加2個文件file.conf和registry.conf
registry.conf和前面的一樣,直接復(fù)制過來就好.
file.conf里的內(nèi)容不同了,新的內(nèi)容如下:
transport {# tcp udt unix-domain-sockettype = "TCP"#NIO NATIVEserver = "NIO"#enable heartbeatheartbeat = true# the client batch send request enableenableClientBatchSendRequest = true#thread factory for nettythreadFactory {bossThreadPrefix = "NettyBoss"workerThreadPrefix = "NettyServerNIOWorker"serverExecutorThread-prefix = "NettyServerBizHandler"shareBossWorker = falseclientSelectorThreadPrefix = "NettyClientSelector"clientSelectorThreadSize = 1clientWorkerThreadPrefix = "NettyClientWorkerThread"# netty boss thread size,will not be used for UDTbossThreadSize = 1#auto default pin or 8workerThreadSize = "default"}shutdown {# when destroy server, wait secondswait = 3}serialization = "seata"compressor = "none" } service { #這里注意,等號前后都是配置,前面是yml里配置的事務(wù)組,后面是register.conf里定義的seata-servervgroupMapping.test_tx_group = "seata_tc_server"#only support when registry.type=file, please don't set multiple addressesseata_tc_server.grouplist = "127.0.0.1:8091"#degrade, current not supportenableDegrade = false#disable seatadisableGlobalTransaction = false }client {rm {asyncCommitBufferLimit = 10000lock {retryInterval = 10retryTimes = 30retryPolicyBranchRollbackOnConflict = true}reportRetryCount = 5tableMetaCheckEnable = falsereportSuccessEnable = false}tm {commitRetryCount = 5rollbackRetryCount = 5}undo {dataValidation = truelogSerialization = "jackson"logTable = "undo_log"}log {exceptionRate = 100} }配置解讀:
transport:與TC交互的一些配置
heartbeat:client和server通信心跳檢測開關(guān)
enableClientBatchSendRequest:客戶端事務(wù)消息請求是否批量合并發(fā)送
service:TC的地址配置,用于獲取TC的地址
vgroupMapping.test_tx_group = “seata_tc_server”:
test_tx_group:是事務(wù)組名稱,要與application.yml中配置一致,
seata_tc_server:是TC服務(wù)端集群的名稱,將來通過注冊中心獲取TC地址
enableDegrade:服務(wù)降級開關(guān),默認(rèn)關(guān)閉。如果開啟,當(dāng)業(yè)務(wù)重試多次失敗后會放棄全局事務(wù)
disableGlobalTransaction:全局事務(wù)開關(guān),默認(rèn)false。false為開啟,true為關(guān)閉
default.grouplist:這個當(dāng)注冊中心為file的時候,才用到
client:客戶端配置
rm:資源管理器配
asynCommitBufferLimit:二階段提交默認(rèn)是異步執(zhí)行,這里指定異步隊列的大小
lock:全局鎖配置
retryInterval:校驗或占用全局鎖重試間隔,默認(rèn)10,單位毫秒
retryTimes:校驗或占用全局鎖重試次數(shù),默認(rèn)30次
retryPolicyBranchRollbackOnConflict:分支事務(wù)與其它全局回滾事務(wù)沖突時鎖策略,默認(rèn)true,優(yōu)先釋放本地鎖讓回滾成功
reportRetryCount:一階段結(jié)果上報TC失敗后重試次數(shù),默認(rèn)5次
tm:事務(wù)管理器配置
commitRetryCount:一階段全局提交結(jié)果上報TC重試次數(shù),默認(rèn)1
rollbackRetryCount:一階段全局回滾結(jié)果上報TC重試次數(shù),默認(rèn)1
undo:undo_log的配置
dataValidation:是否開啟二階段回滾鏡像校驗,默認(rèn)true
logSerialization:undo序列化方式,默認(rèn)Jackson
logTable:自定義undo表名,默認(rèn)是undo_log
log:日志配置
exceptionRate:出現(xiàn)回滾異常時的日志記錄頻率,默認(rèn)100,百分之一概率。回滾失敗基本是臟數(shù)據(jù),無需輸出堆棧占用硬盤空間
2.4 代理DataSource
由于在一階段是通過攔截sql分析語義來生成回滾策略,原來的數(shù)據(jù)源已經(jīng)不夠用了,得換個牛逼的.在服務(wù)里新建一個配置類.
如果是使用的是mybatis
import io.seata.rm.datasource.DataSourceProxy; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;@Configuration public class DataSourceProxyConfig {@Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception {// 因為使用的是mybatis,這里定義SqlSessionFactoryBeanSqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 配置數(shù)據(jù)源代理sqlSessionFactoryBean.setDataSource(new DataSourceProxy(dataSource));return sqlSessionFactoryBean.getObject();} }如果使用的是mybatis-plus
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import io.seata.rm.datasource.DataSourceProxy; import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;@Configuration public class DataSourceProxyConfig {@Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception {// 訂單服務(wù)中引入了mybatis-plus,所以要使用特殊的SqlSessionFactoryBeanMybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();// 代理數(shù)據(jù)源sqlSessionFactoryBean.setDataSource(new DataSourceProxy(dataSource));// 生成SqlSessionFactoryreturn sqlSessionFactoryBean.getObject();} }2.5 加上注解
給事務(wù)發(fā)起者的方法上加上@GlobalTransactional即可,其它的參與者只要加@Transactional就好了.
3.踩坑記錄
1.由于更換了數(shù)據(jù)源,不知道為什么我在yml里給mybatis配置的駝峰映射失效了,導(dǎo)致我查到的數(shù)據(jù)缺少了某些字段.不知道這個問題在mybatis-plus中會不會出現(xiàn).
解決辦法:單獨(dú)給數(shù)據(jù)源配置映射規(guī)則就好了.所以我把上面的配置類加了一個設(shè)置,修改后的代碼如下.
import io.seata.rm.datasource.DataSourceProxy; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import javax.sql.DataSource;@Configuration public class DataSourceProxyConfig {@Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception {// 因為使用的是mybatis,這里定義SqlSessionFactoryBeanSqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 配置數(shù)據(jù)源代理sqlSessionFactoryBean.setDataSource(new DataSourceProxy(dataSource));SqlSessionFactory object = sqlSessionFactoryBean.getObject();assert object != null;// 單獨(dú)給數(shù)據(jù)源設(shè)置駝峰映射object.getConfiguration().setMapUnderscoreToCamelCase(true);return object;} }總結(jié)
- 上一篇: 在线教育项目04_讲师管理前端开发
- 下一篇: hi3518e移植wifi模块注意事项