seata

seata处理分布式事务

  • 1、概述
    • 1.1 seata 是什么
    • 1.2 术语
    • 1.3 安装
      • 修改 file.conf
      • 修改 registry.conf
      • 新建 config.txt
      • 数据库操作
      • 参数同步到Nacos配置中心(参考)
      • git 操作工具安装(启动Nacos)(参考)
  • 2、案例
    • 2.1 业务数据库准备

1、概述

分布式事务问题:

单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源
业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题没法保证
seata_第1张图片

1.1 seata 是什么

Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务

官网

下载:
cloud alibaba 版本对照说明

这里下载的是 1.3.0 版本

1.2 术语

分布式处理过程的 一个 ID + 三个 组件 模型:

  • 全局唯一的事务 ID
    • Transaction ID XID
  • 三组件
    • TC (Transaction Coordinator) - 事务协调者
      维护全局和分支事务的状态,驱动全局事务提交或回滚
    • TM (Transaction Manager) - 事务管理器
      定义全局事务的范围:开始全局事务、提交或回滚全局事务
    • RM (Resource Manager) - 资源管理器
      管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚

处理过程:
seata_第2张图片

Seata 分布式交易解决方案:
seata_第3张图片

1.3 安装

下载地址

此处下载的是 1.3.0 版本

修改 file.conf

解压之后,修改 conf 目录下的 file.conf 配置文件(先备份)

默认file,修改为db: mode = “db”

注意数据库 8.0 需要改:driverClassName = “com.mysql.cj.jdbc.Driver”

修改为自己的数据库配置:url = “jdbc:mysql://127.0.0.1:3306/seata”

## transaction log store, only used in seata-server
store {
  ## store mode: file、db、redis
  
  # 默认file,修改为db
  mode = "db"

  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    
    # 注意数据库 8.0 需要加上 .jc
    driverClassName = "com.mysql.cj.jdbc.Driver"
    
    # 修改为自己的数据库配置
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "mysql"
    password = "mysql"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }

  ## redis store property
  redis {
    host = "127.0.0.1"
    port = "6379"
    password = ""
    database = "0"
    minConn = 1
    maxConn = 10
    queryLimit = 100
  }

}

修改 registry.conf

修改 conf 目录下的 registry.conf 配置文件(先备份)

默认file,修改为nacos :registry { type = “nacos”
默认file,修改为nacos :config { type = “nacos”

注意nacos地址:serverAddr = “127.0.0.1:8848”

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  # 默认file,修改为nacos
  type = "nacos"

  nacos {
    application = "seata-server"
    serverAddr = "127.0.0.1:8848"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
  eureka {
    serviceUrl = "http://localhost:8761/eureka"
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = 0
    password = ""
    cluster = "default"
    timeout = 0
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
  }
  etcd3 {
    cluster = "default"
    serverAddr = "http://localhost:2379"
  }
  sofa {
    serverAddr = "127.0.0.1:9603"
    application = "default"
    region = "DEFAULT_ZONE"
    datacenter = "DefaultDataCenter"
    cluster = "default"
    group = "SEATA_GROUP"
    addressWaitTime = "3000"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  # 默认file,修改为nacos
  type = "nacos"

  nacos {
    serverAddr = "127.0.0.1:8848"
    namespace = ""
    group = "SEATA_GROUP"
    username = ""
    password = ""
  }
  consul {
    serverAddr = "127.0.0.1:8500"
  }
  apollo {
    appId = "seata-server"
    apolloMeta = "http://192.168.1.204:8801"
    namespace = "application"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    name = "file.conf"
  }
}

新建 config.txt

该文件目录地址存放 conf/ 下,文件内容如下:

配置事务分组:service.vgroupMapping.seata_test_group=default

配置数据库相关信息

transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=false
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3

# 此处可以修改为自己项目的分组
#service.vgroup_mapping.my_test_tx_group=default
## 1.0之后需要换成  vgroupMapping
## 可以写多个配置,只需要相关联的group统一就行
service.vgroupMapping.seata_test_group=default

service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=false
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=false
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000

#此处配置file.conf一致
store.mode=db

store.publicKey=
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100

store.db.datasource=druid
store.db.dbType=mysql
#配置数据库相关信息
store.db.driverClassName=com.mysql.cj.jdbc.Driver
##store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://192.168.99.100:3306/seata?useUnicode=true
store.db.user=root
store.db.password=root
icKeyRetrieval=true
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000

store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

数据库操作

在 mysql 中新建数据库 seata,并在库里建表

在源码包的\script\server\db文件夹下,有 mysql.sql 文件,运行即可
seata_第4张图片

参数同步到Nacos配置中心(参考)

在源码包的/script/config-center/nacos文件夹下,将nacos-config.sh文件复制到conf目录下,如下:
seata_第5张图片
内容如下:

#!/usr/bin/env bash
# Copyright 1999-2019 Seata.io Group.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at、
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

while getopts ":h:p:g:t:u:w:" opt
do
  case $opt in
  h)
    host=$OPTARG
    ;;
  p)
    port=$OPTARG
    ;;
  g)
    group=$OPTARG
    ;;
  t)
    tenant=$OPTARG
    ;;
  u)
    username=$OPTARG
    ;;
  w)
    password=$OPTARG
    ;;
  ?)
    echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
    exit 1
    ;;
  esac
done

urlencode() {
  for ((i=0; i < ${#1}; i++))
  do
    char="${1:$i:1}"
    case $char in
    [a-zA-Z0-9.~_-]) printf $char ;;
    *) printf '%%%02X' "'$char" ;;
    esac
  done
}

if [[ -z ${host} ]]; then
    host=localhost
fi
if [[ -z ${port} ]]; then
    port=8848
fi
if [[ -z ${group} ]]; then
    group="SEATA_GROUP"
fi
if [[ -z ${tenant} ]]; then
    tenant=""
fi
if [[ -z ${username} ]]; then
    username=""
fi
if [[ -z ${password} ]]; then
    password=""
fi

nacosAddr=$host:$port
contentType="content-type:application/json;charset=UTF-8"

echo "set nacosAddr=$nacosAddr"
echo "set group=$group"

failCount=0
tempLog=$(mktemp -u)
function addConfig() {
  curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$(urlencode $1)&group=$group&content=$(urlencode $2)&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
  if [[ -z $(cat "${tempLog}") ]]; then
    echo " Please check the cluster status. "
    exit 1
  fi
  if [[ $(cat "${tempLog}") =~ "true" ]]; then
    echo "Set $1=$2 successfully "
  else
    echo "Set $1=$2 failure "
    (( failCount++ ))
  fi
}

count=0
# 这里可能和官网给出的不一样,那是因为我修改了,方便两个文件放在同一路径下
for line in $(cat $(dirname "$PWD")/config.txt | sed s/[[:space:]]//g); do
  (( count++ ))
	key=${line%%=*}
    value=${line#*=}
	addConfig "${key}" "${value}"
done

echo "========================================================================="
echo " Complete initialization parameters,  total-count:$count ,  failure-count:$failCount "
echo "========================================================================="

if [[ ${failCount} -eq 0 ]]; then
	echo " Init nacos config finished, please start seata-server. "
else
	echo " init nacos config fail. "
fi

注意:

如果需要保证config.txtnacos-config.sh文件在相同路径下,你可以定义其中的.sh中的逻辑:
seata_第6张图片

git 操作工具安装(启动Nacos)(参考)

startup.cmd -m standalone 启动 Nacos

先在 Nacos 上面新建命名空间 seata
seata_第7张图片

使用 Git 将nacos的配置信息推送至nacos上。(必须保证nacos已启动!)

nacos-config.sh文件路径下开启Git bash视窗工具

使用如下指令实现配置推送至nacos:

sh nacos-config.sh -h 127.0.0.1 -p 8848 -g seata -t b1c7bf6e-f921-4687-86f8-b8be8bcb81ac -u nacos -w nacos

命令说明:

  • -h:host,默认值 localhost
  • -p:port,指定nacos的端口地址,默认值 8848
  • -g :指定配置的分组,注意,是配置的分组,默认值为 ‘SEATA_GROUP’
  • -t :租户信息,指定 Nacos 命名空间 ID 字段, 默认值为空
  • -u -w:指定nacos的用户名和密码,开启了nacos注册和配置认证的才需要指定

命令执行完成后,git bash界面如下所示:
seata_第8张图片

此时刷新nacos对应工作区间seata,如下所示:
seata_第9张图片
此时表示seata的配置已经存放至nacos中

2、案例

2.1 业务数据库准备

你可能感兴趣的:(笔记,java,微服务,spring,cloud)