seata 1.0教程
技術選型及版本
spring-cloud-starter-alibaba-seata
spring-cloud-alibaba:1.5.1.RELEASE
springcloud:Edgware.SR4
seata-all:1.0.0
springboot:1.5.4
mybatis-spring-boot-starter.version:2.0.0
java:jdk8
1.啓動seata server
下載包:https://github.com/seata/seata/releases
解壓:tar -xzvf seata-server-1.0.0.tar.gz
修改配置:
1.配置registry.conf
[root@jr-test conf]# cat registry.conf
//註冊中心
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "eureka" //註冊中心類型
nacos {
serverAddr = "localhost"
namespace = ""
cluster = "default"
}
eureka {
serviceUrl = "http://192.xx.xx.xx:8761/eureka" //註冊中心地址
application = "seata-server" //tc註冊時的名稱
weight = "1"
}
//......支持多種
}
//配置中心
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "file" //配置中心類型
file {
name = "file.conf" //
}
//......支持多種
}
2.配置file.conf
[root@jr-test conf]# cat file.conf
service {
#transaction service group mapping
vgroup_mapping.fsp_tx_group = "fsp-tx" //事務分組,非常重要,client和tc一定要一致,fsp_tx_group是個自定義的分組名稱
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8091"
#disable seata
disableGlobalTransaction = false
}
## transaction log store, only used in seata-server
store {
## store mode: file、db
mode = "db" //事務日誌存儲模式
## file store property
file {
## store location dir
dir = "sessionStore"
}
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "dbcp"
## mysql/oracle/h2/oceanbase etc.
db-type = "mysql"
driver-class-name = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://192.xx.xx.xx:3306/seata" // tc的數據庫,可自定義命名,對應就好
user = "root"
password = "xxx"
}
}
3.建表
全局事務會話信息由3塊內容構成:
- 全局事務 global_table
- 分支事務 branch_table
- 全局鎖 lock_table
建表語句在:https://github.com/seata/seata/tree/develop/script/server/db
4.啓動tc
bin目錄下:
nohup sh seata-server.sh -h xx.xx.xx.xx -p 8091 -m db -n 1 &
這裏是以nohup的方式後臺啓動,參數可選:
-h: 註冊到註冊中心的ip
-p: Server rpc 監聽端口
-m: 全局事務會話信息存儲模式,file、db,優先讀取啓動參數
-n: Server node,多個Server時,需區分各自節點,用於生成不同區間的transactionId,以免衝突
-e: 多環境配置參考 http://seata.io/en-us/docs/ops/multi-configuration-isolation.html
2.client端引入seata依賴
目前有三種方式,相應的支持程度不同:
依賴 | 支持yml配置 | 實現xid傳遞 | 支持數據源自動代理 | 自動初始化GlobalTransactionScanner入口 |
---|---|---|---|---|
seata-all | 否 | 否 | 是 | 否 |
seata-spring-boot-starter | 是 | 否 | 是 | 是 |
spring-cloud-alibaba-seata | 否 | 是 | 是 | 是 |
不建議用戶僅引入seata-all,需要自行實現的東西太多。
spring-cloud-alibaba-seata,2.1.0內嵌seata-all 0.7.1,2.1.1內嵌seata-all 0.9.0。建議排除掉,引入1.0;
(可參考官方文檔:http://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html)
我們這裏以引入spring-cloud-alibaba-seata 依賴爲例,下面僅展示與seata相關的依賴:
<properties>
<spring-cloud.version>Edgware.SR4</spring-cloud.version>
<spring-cloud-alibaba.version>1.5.1.RELEASE</spring-cloud-alibaba.version>
<seata-version>1.0.0</seata-version>
</properties>
<dependencies>
<!--seata-all-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>${seata-version}</version>
</dependency>
<!--sca-seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!--Spring Cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--Spring Cloud Alibaba,包含seata-all 0.9,這裏排除掉,換爲1.0-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
<exclusions>
<exclusion>
<artifactId>seata-all</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
3.client端引入配置文件
seata server端和client端的腳本和配置,都彙總在這裏,client端整合時,去找對應的文件複製過來修改。
https://github.com/seata/seata/tree/develop/script
1.修改bootstrap.yml
添加事務分組
spring:
cloud:
alibaba:
seata:
tx-service-group: fsp_tx_group
這個分組名稱自定義,但是seata server端,client端要保持一致。
2.配置file.conf
引入配置文件,並修改相關配置,由於有很多配置項,不是每個都需要去改一遍,這裏只是改動少數,讓你先能整合進去跑起來,其他的參數後面再自己調整。
file.conf
//省略很多
service {
#transaction service group mapping
vgroup_mapping.default = "default"
#only support when registry.type=file, please don't set multiple addresses
default.grouplist = "127.0.0.1:8091"
#degrade, current not support
enableDegrade = false
#disable seata
disableGlobalTransaction = false
}
client {
//省略很多
rm {
report.success.enable = true //一階段成功後是否上報tc,這個配置可以提高性能
}
support {
# auto proxy the DataSource bean //數據源自動代理
spring.datasource.autoproxy = false
}
}
3.配置registry.conf
註冊中心和配置中心,都支持多種,按照自己的技術選型,修改對應的配置。
registry {
# file 、nacos 、eureka、redis、zk
type = "eureka"
eureka {
serviceUrl = "http://192.xx.xx.xx:8761/eureka"
application = "default"
weight = "1"
}
//省略
}
config {
# file、nacos 、apollo、zk
type = "file"
file {
name = "file.conf"
}
//省略
}
4.配置數據源頭代理
如果支持自動代理,那就開啓配置就好,這裏示例下使用mysql和mybatis時,如何自行代理數據源。
package io.seata.sample;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
/**
* 數據源代理
* @author IT雲清
*/
@Configuration
public class DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Primary
@Bean("dataSource")
public DataSourceProxy dataSource(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();
}
}
5.實現xid傳遞
如果你引入的依賴和技術選型,沒有實現xid傳遞等邏輯,你需要參考源碼integration文件夾下的各種rpc實現 module。
https://github.com/seata/seata/tree/develop/integration
6.實現scanner入口
如果你引入的依賴和技術選型,沒有實現初始化GlobalTransactionScanner邏輯,可以自行實現如下:
1.SeataProperties.java
@ConfigurationProperties("spring.cloud.alibaba.seata")
public class SeataProperties {
private String txServiceGroup;
public SeataProperties() {
}
public String getTxServiceGroup() {
return this.txServiceGroup;
}
public void setTxServiceGroup(String txServiceGroup) {
this.txServiceGroup = txServiceGroup;
}
}
2.初始化GlobalTransactionScanner
package com.runlion.fsp.credit.seata.config;
import com.runlion.fsp.credit.seata.SeataProperties;
import io.seata.spring.annotation.GlobalTransactionScanner;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author IT雲清
*/
@Configuration
@EnableConfigurationProperties({SeataProperties.class})
public class GlobalTransactionAutoConfiguration {
private static final String APPLICATION_NAME_PREFIX = "spring.application.name";
private static final String DEFAULT_TX_SERVICE_GROUP_SUFFIX = "-seata-service-group";
private final ApplicationContext applicationContext;
private final SeataProperties seataProperties;
public GlobalTransactionAutoConfiguration(
ApplicationContext applicationContext,
SeataProperties seataProperties) {
this.applicationContext = applicationContext;
this.seataProperties = seataProperties;
}
/**
* If there is no txServiceGroup,use the default
* @return GlobalTransactionScanner the entrance
*/
@Bean
public GlobalTransactionScanner globalTransactionScanner(){
String applicationName = this.applicationContext.getEnvironment().getProperty(APPLICATION_NAME_PREFIX);
String txServiceGroup = seataProperties.getTxServiceGroup();
if(StringUtils.isEmpty(txServiceGroup)){
txServiceGroup = applicationName + DEFAULT_TX_SERVICE_GROUP_SUFFIX;
this.seataProperties.setTxServiceGroup(txServiceGroup);
}
return new GlobalTransactionScanner(applicationName,txServiceGroup);
}
}
7.建表
如果要使用seata分佈式事務,當前服務就需要建一張undolog表。
建表語句參考:https://github.com/seata/seata/tree/develop/script/client/at/db
8.使用
- 1.@GlobalTransaction 全局事務註解
- 2.@GlobalLock 防止髒讀和髒寫,又不想納入全局事務管理時使用。(不需要rpc和xid傳遞等成本)