事务篇(三):seata分布式事务

0、seata 在Windows下的启动

我本地和生产环境和都是用的SeaTa-0.9.0 版本,1.0.0 版本以后的配置会有些不同,所以大家注意一下
下载:https://github.com/seata/seata/releases/tag/v0.9.0
在这里插入图片描述
修改seata-server配置文件:

2.1.registry.conf文件

registry {
    
    
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"   #注册中心采用nacos

  nacos {
    
    
    serverAddr = "localhost:8848"
    namespace = ""
    cluster = "default"
  }
}

config {
    
    
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"  #配置中心直接使用file模式

  file {
    
    
    name = "file.conf"
  }
}

2.2file.conf文件(存储方式采用db->58行,并且修改db信息->82~85行)

transport {
    
    
  # tcp udt unix-domain-socket
  type = "TCP"
  #NIO NATIVE
  server = "NIO"
  #enable heartbeat
  heartbeat = true
  #thread factory for netty
  thread-factory {
    
    
    boss-thread-prefix = "NettyBoss"
    worker-thread-prefix = "NettyServerNIOWorker"
    server-executor-thread-prefix = "NettyServerBizHandler"
    share-boss-worker = false
    client-selector-thread-prefix = "NettyClientSelector"
    client-selector-thread-size = 1
    client-worker-thread-prefix = "NettyClientWorkerThread"
    # netty boss thread size,will not be used for UDT
    boss-thread-size = 1
    #auto default pin or 8
    worker-thread-size = 8
  }
  shutdown {
    
    
    # when destroy server, wait seconds
    wait = 3
  }
  serialization = "seata"
  compressor = "none"
}
service {
    
    
  #vgroup->rgroup
  vgroup_mapping.my_test_tx_group = "default"  
#注意这里的名称与客户端yml文件中的spring-cloud-alibaba-seata-tx-service-group 的值一致
  #only support single node
  default.grouplist = "172.18.44.110:8091" #采用service端服务器的ip
  #degrade current not support
  enableDegrade = false
  #disable
  disable = false
  #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
  max.commit.retry.timeout = "-1"
  max.rollback.retry.timeout = "-1"
}

client {
    
    
  async.commit.buffer.limit = 10000
  lock {
    
    
    retry.internal = 10
    retry.times = 30
  }
  report.retry.count = 5
  tm.commit.retry.count = 1
  tm.rollback.retry.count = 1
}

## transaction log store
store {
    
    
  ## store mode: file、db
  mode = "db"   #采用db储存信息

  ## file store
  file {
    
    
    dir = "sessionStore"

    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    max-branch-session-size = 16384
    # globe session size , if exceeded throws exceptions
    max-global-session-size = 512
    # file buffer size , if exceeded allocate new buffer
    file-write-buffer-cache-size = 16384
    # when recover batch read size
    session.reload.read_size = 100
    # async, sync
    flush-disk-mode = async
  }

  ## database store
  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"     #db的连接信息
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "root"
    password = "root"
    min-conn = 1
    max-conn = 3
    global.table = "global_table"
    branch.table = "branch_table"
    lock-table = "lock_table"
    query-limit = 100
  }
}
lock {
    
    
  ## the lock store mode: local、remote
  mode = "remote"

  local {
    
    
    ## store locks in user's database
  }

  remote {
    
    
    ## store locks in the seata's server
  }
}
recovery {
    
    
  #schedule committing retry period in milliseconds
  committing-retry-period = 1000
  #schedule asyn committing retry period in milliseconds
  asyn-committing-retry-period = 1000
  #schedule rollbacking retry period in milliseconds
  rollbacking-retry-period = 1000
  #schedule timeout retry period in milliseconds
  timeout-retry-period = 1000
}

transaction {
    
    
  undo.data.validation = true
  undo.log.serialization = "jackson"
  undo.log.save.days = 7
  #schedule delete expired undo_log in milliseconds
  undo.log.delete.period = 86400000
  undo.log.table = "undo_log"
}

## metrics settings
metrics {
    
    
  enabled = false
  registry-type = "compact"
  # multi exporters use comma divided
  exporter-list = "prometheus"
  exporter-prometheus-port = 9898
}

support {
    
    
  ## spring
  spring {
    
    
    # auto proxy the DataSource bean
    datasource.autoproxy = false
  }
}

3.1.创建seata数据库,在你下载包的 conf/db_store.sql 这个位置
在这里插入图片描述
如果没有找到相应脚本,可以去官网找一下,这里列出我找到的mysql版本
db_store
undo_log

4.运行

windows进入/seata/bin/里 , 双击.bat 文件即可

在这里插入图片描述

Linux下:

进入/seata/bin
启动服务端 /seata/bin# sh seata-server.sh

1、理论

Seata主要由三个重要组件组成:

  • TC:Transaction Coordinator 事务协调器,管理全局的分支事务的状态,用于全局性事务的提交和回滚。

  • TM:Transaction Manager 事务管理器,用于开启、提交或者回滚全局事务。

  • RM:Resource Manager 资源管理器,用于分支事务上的资源管理,向TC注册分支事务,上报分支事务的状态,接受TC的命令来提交或者回滚分支事务。
    在这里插入图片描述

  • Seata的执行流程如下:

    1.A服务的TM向TC申请开启一个全局事务,TC就会创建一个全局事务并返回一个唯一的XID
    2.A服务的RM向TC注册分支事务,并及其纳入XID对应全局事务的管辖
    3.A服务执行分支事务,向数据库做操作
    4.A服务开始远程调用B服务,此时XID会在微服务的调用链上传播
    5.B服务的RM向TC注册分支事务,并将其纳入XID对应的全局事务的管辖
    6.B服务执行分支事务,向数据库做操作
    7.全局事务调用链处理完毕,TM根据有无异常向TC发起全局事务的提交或者回滚
    8.TC协调其管辖之下的所有分支事务, 决定是否回滚

  • Seata实现2PC与传统2PC的差别:

    架构层次方面,传统2PC方案的 RM 实际上是在数据库层,RM本质上就是数据库自身,通过XA协议实现,而 Seata的RM是以jar包的形式作为中间件层部署在应用程序这一侧的。

    两阶段提交方面,传统2PC无论第二阶段的决议是commit还是rollback,事务性资源的锁都要保持到Phase2完成才释放。而Seata的做法是在Phase1 就将本地事务提交,这样就可以省去Phase2持锁的时间,整体提高效率。

  • Seata实现分布式事务控制
    本示例通过Seata中间件实现分布式事务,模拟电商中的下单和扣库存的过程
    我们通过订单微服务执行下单操作,然后由订单微服务调用商品微服务扣除库存
    在这里插入图片描述

2、实战(seata项目示例)

seata项目示例之快速部署
本章节将使用官方示例seata-demo项目

第一步:下载源代码:

git clone https://gitee.com/leitingweb/seata-demo.git

导入项目后,项目整体结构如下图所示:
在这里插入图片描述
第二步: 修改seata-server配置文件

seata-server是seata中的事务协调器,该项目由两个主要的配置文件 registy.conf和file.conf,文件位置如下图所示:
在这里插入图片描述
(1)registry.conf

默认情况下,seata-server的配置模式是file模式,由registy.conf的registy.type和config.type属性确定,该模式下seata-server的配置都是走配置文件,该配置文件的名称在registry.file.name和config.file.name属性中确定,默认都是file.conf,因此,该项目在不修改配置文件的情况下也可以正常启动,走默认配置。

当然也支持nacos 、eureka、redis、zk、consul、etcd3、sofa等多种配置方式,这里要说明一下,生产环境下一般我们采用集群模式,所以配置最好在nacos的配置中心。本文使用默认的file模式,删除其他无用的配置方式后,registry.conf的结构精简如下:

registry {
    
    
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "file"

  file {
    
    
    name = "file.conf"
  }
}

config {
    
    
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"
  file {
    
    
    name = "file.conf"
  }
}

(2)file.conf文件

file文件主要配置seata-server的各种属性,也可以完全不修改,走默认配置,本文在此重点讲一下store模块

seata-server的存储模式有file和db两种,可以通过store.mode属性配置,默认的存储方式是file。

file模式下,seata的事务相关信息会走内存,并持久化到root.data文件中,这种模式性能较高。

db模式是一种高可用的模式,seata的全局事务,分支事务和锁都在数据库中存储,相关表都在all_in_one.sql文件中。

如果是db模式,找到db模块 修改数据库配置信息,根据自己的数据库,修改数据库IP,端口号,用户名和密码,具体如下:

  • transaction log store
store {
    
    
  ## store mode: file、db
  mode = "file"

  ## file store
  file {
    
    
    dir = "sessionStore"

    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    max-branch-session-size = 16384
    # globe session size , if exceeded throws exceptions
    max-global-session-size = 512
    # file buffer size , if exceeded allocate new buffer
    file-write-buffer-cache-size = 16384
    # when recover batch read size
    session.reload.read_size = 100
    # async, sync
    flush-disk-mode = async
  }
  • database store
 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://***:3306/seata"
    user = "***"
    password = "***"
    min-conn = 1
    max-conn = 3
    global.table = "global_table"
    branch.table = "branch_table"
    lock-table = "lock_table"
    query-limit = 100
  }
}

第三步 修改spingboot-mybatis项目的配置文件

在这里插入图片描述

springboot-mybatis项目是一个父子项目,在本例中用于模拟分布式事务场景,结构如上图所示,该项目包含了几个业务子项目,分别是:

账户:sbm-account-service

业务:sbm-business-service

订单:sbm-order-service

库存:sbm-storage-service

需要分别修改以上几个项目的相关配置文件,以sbm-account-service项目为例:

修改application.properties文件
在这里插入图片描述
主要修改该配置文件的数据库连接信息,根据自己的数据库,修改数据库IP,端口号,用户名和密码

spring.application.name=account-service
server.port=8083
spring.datasource.url=jdbc:mysql://****:3306/seata?useSSL=false&serverTimezone=UTC
spring.datasource.username=***
spring.datasource.password=***
spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group
logging.level.io.seata=info
logging.level.io.seata.samples.account.persistence.AccountMapper=debug

注意seata-server中的db配置是配置用于存储seata事务相关的信息,此处的数据库配置是业务系统的业务数据库,官方示例中,seata事务库和业务库合并为一个了,实际业务中建议分开。

其他几个项目依次类推

第四步:执行sql文件:
在这里插入图片描述
执行SQL文件中的SQL语句,创建数据库和表

第四步,启动项目:

(1)启动seata-server:

打开seata-server工程的Server类,运行该类的main方法,启动项目:
在这里插入图片描述
启动成功后,会在控制台打出如下日志:

2019-09-26 15:37:27.711 INFO [main]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load TransactionStoreManager[FILE] extension by class[io.seata.server.store.file.FileTransactionStoreManager]
2019-09-26 15:37:27.713 INFO [main]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load SessionManager[FILE] extension by class[io.seata.server.session.file.FileBasedSessionManager]
2019-09-26 15:37:28.188 INFO [main]io.seata.core.rpc.netty.AbstractRpcRemotingServer.start:156 -Server started ...

(2)启动springboot-mybayis项目中的各业务子项目,同样以sbm-account-service项目为例:

打开SpringbootMybatisAccountApplication类,运行该类的main方法,启动项目

项目成功启动后,打印如下日志:

2019-09-26 15:48:14.466  INFO 16220 ---  main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8083 (http) with context path ''
2019-09-26 15:48:14.469  INFO 16220 --- [main] .s.a.SpringbootMybatisAccountApplication : Started SpringbootMybatisAccountApplication in 2.961 seconds (JVM running for 3.605)
2019-09-26 15:48:17.821  INFO 16220 --- [imeoutChecker_1] i.s.c.r.netty.NettyClientChannelManager  : will connect to 127.0.0.1:8091
2019-09-26 15:48:17.823  INFO 16220 --- [imeoutChecker_1] i.s.core.rpc.netty.NettyPoolableFactory  : NettyPool create channel to transactionRole:TMROLE,address:127.0.0.1:8091,msg:< RegisterTMRequest{
    
    applicationId='account-service', transactionServiceGroup='my_test_tx_group'} >
2019-09-26 15:48:17.846  INFO 16220 --- [imeoutChecker_1] i.s.core.rpc.netty.NettyPoolableFactory  : register success, cost 17 ms, version:0.8.1,role:TMROLE,channel:[id: 0x02230a52, L:/127.0.0.1:60607 - R:/127.0.0.1:8091]

sbm-account-service启动成功后,会在seata-server 进行注册,注册成功后在seata-server服务下打印如下日志:

//todo

2019-09-26 15:51:32.050 INFO [NettyServerNIOWorker_1_8]io.seata.common.loader.EnhancedServiceLoader.loadFile:237 -load Codec[SEATA] extension by class[io.seata.codec.seata.SeataCodec]
2019-09-26 15:51:32.068 INFO [ServerHandlerThread_1_500]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegRmMessage:114 -rm register success,message:RegisterRMRequest{
    
    resourceIds='jdbc:mysql://***:3306/seata', applicationId='account-service', transactionServiceGroup='my_test_tx_group'},channel:[id: 0x5efef77e, L:/127.0.0.1:8091 - R:/127.0.0.1:60690]
2019-09-26 15:51:35.831 INFO [NettyServerNIOWorker_2_8]io.seata.core.rpc.DefaultServerMessageListenerImpl.onRegTmMessage:131 -checkAuth for client:127.0.0.1:60698 vgroup:my_test_tx_group ok

至此,sbm-account-service项目启动成功

此后依次启动剩余几个项目:各项目启动类如下:

sbm-business-service :SpringbootMybatisBusinessApplication

sbm-order-service: SpringbootMybatisOrderApplication

sbm-storage-service:SpringbootMybatisStorageApplication

至此,所有项目启动成功!

浏览器中输入:http://localhost:8084/api/business/purchase/commit

可以模拟一个商品下单的分布式事务过程,具体过程见seata项目示例之一个完整的分布式事务过程。

3、seata 使用nacos 作为配置中心

资料:https://blog.csdn.net/jixieguang/article/details/110621561#3nacos_16

猜你喜欢

转载自blog.csdn.net/YL3126/article/details/120712138
今日推荐