首页 > 其他分享 >分布式事务 Seata 集群搭建

分布式事务 Seata 集群搭建

时间:2023-11-20 22:58:08浏览次数:33  
标签:Seata lock db server 集群 mysql 分布式 seata

Seata 是蚂蚁金服和阿里巴巴共同开源的一款分布式事务项目,致力于在微服务架构下提供高性能和简单易用的分布式事务解决方案。自诞生以来就备受国内开发人员推崇,在实际工作中使用者甚多。Seata 提供了四种不同的分布式事务解决方案:

  • XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
  • TCC模式:最终一致的分阶段事务模式,有业务侵入
  • AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
  • SAGA模式:长事务模式,有业务侵入

在实际工作中,比较常用的是前三种模式(XA、TCC、AT),在后面的博客中会进行介绍,SAGA 模式很少使用,就不再介绍了。本篇博客先介绍如何进行 Seata 集群的搭建(如果会搭建集群,那么搭建单节点也很容易)。

Seata 的官网地址是:http://seata.io


一、准备工作

本篇博客参考 Seata 官网的部署文档,采用 docker-compose 进行集群部署。

默认情况下 Seata 是采用文件进行注册、配置和存储的,但是实际工作中并不会采用这种模式。

因此我们直接使用 nacos 作为注册中心和配置中心,使用 mysql 作为 Seata 的数据存储。

由于本篇博客主要介绍如何进行 Seata 集群的搭建,因此有关 nacos 和 mysql 的搭建,这里不做介绍。

我的虚拟机操作系统为 CentOS7( ip地址为 192.168.136.128 ),已经部署好了 nacos 和 mysql,其中 nacos 无需账号密码就可以访问;虚拟机上也安装好了 docker 和 docker-compose

首先到 GitHub 下载最新版的 Seata ,本篇博客在编写时,Seata 的最新版本号是 1.8.0

Seata 的 GitHub 下载地址为:https://github.com/seata/seata/releases

image

可以把 seata-server.zip 和源码文件包都下载下来,会下载到 2 个文件:

  • seata-server-1.8.0.zip 是 Seata 的服务端文件

  • seata-1.8.0.zip 是源代码文件

之所以要下载 seata-server-1.8.0.zip 是因为:如果你想快速使用的话,可以很方便的直接在 windows 上启动 Seata 服务。

之所以下载 seata-1.8.0.zip 源码文件,是因为其内部包含部署所需要的文件。linux 部署 Seata 只需要下载源码文件即可。

解压缩 seata-1.8.0.zip 源码文件,我们在部署过程中,需要使用的文件在解压后的文件夹路径为:

  • server\src\main\resources 目录下的 application.yml 和 application.example.yml,这是 Seata 服务端的配置文件和配置样例参考文件。

  • script\server\db 目录下的 mysql.sql ,这是 Seata 服务端在 mysql 中的建表文件。

  • script\client\at\db 目录下的 mysql.sql ,这个是在使用 AT 模式时需要在客户端微服务所连接 mysql 中的建表文件。

其中 script\client\at\db 目录下的 mysql.sql 文件,这里先不用,我们在后续介绍 Seata 的 AT 事务模式时再使用。


二、集群搭建

我们部署的是 3 节点的 Seata 集群,首先在虚拟机上先创建好 docker-compose 部署的目录结构:

首先创建一个目录 /app/seata,在其下面创建 3 个子目录,每个目录下拷贝一个 application.yml 文件:

image

参照 application.example.yml,我们使用 nacos 作为注册中心,使用 mysql 作为 seata 数据存储,需要修改配置。

以 server1 为例,其修改后的 application.yml 配置内容如下:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${log.home:${user.home}/logs/seata}

console:
  user:
    username: seata
    password: seata

seata:
  config:
    type: nacos
    nacos:
      server-addr: 192.168.136.128:8848
      namespace:
      #username:
      #password:
      #context-path:
      group: SEATA_GROUP
      data-id: seataServer.properties

  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 192.168.136.128:8848
      group: SEATA_GROUP
      namespace:
      cluster: jobs
      #username:
      #password:
      #context-path:

#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /, /**/*.css, /**/*.js, /**/*.html, /**/*.map, /**/*.svg, /**/*.png, /**/*.jpeg, /**/*.ico, /api/v1/auth/login
  • server 下配置的端口 7091 是 seata 的 web 界面访问的端口,其数据通信端口如果不配置的话,默认在此基础上加 1000,也就是 8091

  • console 下配置的用户名和密码,是登录 seata 的 web 界面的账号和密码,默认都是字符串 seata

  • setata 的 config 和 setata 的 registry 下面都是配置 nacos 的连接方式,表示使用 nacos 作为配置中心和注册中心

在 setata 的 config 下的 data-id 配置的文件名是 seataServer.properties,表示 seata 启动后会去 nacos 的配置中心上读取该文件进行服务配置,因此根据 config 下的 nacos 配置,我们需要在 nacos 的配置中心中创建出该文件:

image

其 Properties 文件的配置内容如下:(主要配置的是 Seata 服务端连接 mysql 的信息)

store.mode=db
#-----db-----
store.db.datasource=druid
store.db.dbType=mysql
# 需要根据mysql的版本调整driverClassName
# mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
# mysql8以下版本的driver:com.mysql.jdbc.Driver
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://192.168.136.128:3306/seata?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
store.db.user=root
store.db.password=root
# 数据库初始连接数
store.db.minConn=1
# 数据库最大连接数
store.db.maxConn=20
# 获取连接时最大等待时间 默认5000,单位毫秒
store.db.maxWait=5000
# 全局事务表名 默认global_table
store.db.globalTable=global_table
# 分支事务表名 默认branch_table
store.db.branchTable=branch_table
# 全局锁表名 默认lock_table
store.db.lockTable=lock_table
# 查询全局事务一次的最大条数 默认100
store.db.queryLimit=100


# undo保留天数 默认7天,log_status=1(附录3)和未正常清理的undo
server.undo.logSaveDays=7
# undo清理线程间隔时间 默认86400000,单位毫秒
server.undo.logDeletePeriod=86400000
# 二阶段提交重试超时时长 单位ms,s,m,h,d,对应毫秒,秒,分,小时,天,默认毫秒。默认值-1表示无限重试
# 公式: timeout>=now-globalTransactionBeginTime,true表示超时则不再重试
# 注: 达到超时时间后将不会做任何重试,有数据不一致风险,除非业务自行可校准数据,否者慎用
server.maxCommitRetryTimeout=-1
# 二阶段回滚重试超时时长
server.maxRollbackRetryTimeout=-1
# 二阶段提交未完成状态全局事务重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.committingRetryPeriod=1000
# 二阶段异步提交状态重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.asynCommittingRetryPeriod=1000
# 二阶段回滚状态重试回滚线程间隔时间  默认1000,单位毫秒
server.recovery.rollbackingRetryPeriod=1000
# 超时状态检测重试线程间隔时间 默认1000,单位毫秒,检测出超时将全局事务置入回滚会话管理器
server.recovery.timeoutRetryPeriod=1000

根据配置的数据库连接字符串,我们需要在 mysql 数据库中,运行 sql 脚本创建出 Seata 服务端所需要的表:

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
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_status_gmt_modified` (`status` , `gmt_modified`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

-- 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(6),
    `gmt_modified`      DATETIME(6),
    PRIMARY KEY (`branch_id`),
    KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(128),
    `transaction_id` BIGINT,
    `branch_id`      BIGINT       NOT NULL,
    `resource_id`    VARCHAR(256),
    `table_name`     VARCHAR(32),
    `pk`             VARCHAR(36),
    `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
    `gmt_create`     DATETIME,
    `gmt_modified`   DATETIME,
    PRIMARY KEY (`row_key`),
    KEY `idx_status` (`status`),
    KEY `idx_branch_id` (`branch_id`),
    KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

CREATE TABLE IF NOT EXISTS `distributed_lock`
(
    `lock_key`       CHAR(20) NOT NULL,
    `lock_value`     VARCHAR(20) NOT NULL,
    `expire`         BIGINT,
    primary key (`lock_key`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8mb4;

INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

OK,以上步骤完成后,Setata 的第一个节点就搞定了,由于剩下两个节点也是到 naocs 上读取配置,连接的 mysql 也相同,因此剩下两个节点,只需要把 server1 下面的 application.yml 拷贝到 server2 和 server3 目录下即可,最好修改一下端口号。

将 server2 下的 application.yml 中的 server 端口修改为 7092,server3 下的 yml 中端口修改为 7093

最后在 /app/seata 目录下创建的 docker-compose.yml 的文件,填写一下内容即可:

version: "3.2"
services:
  seata1:
    image: seataio/seata-server:1.8.0
    container_name: seata1
    restart: always
    ports:
      - 7091:7091
      - 8091:8091
    environment:
      - SEATA_IP=192.168.136.128
      - SEATA_PORT=8091
      # 服务节点
      - SERVER_NODE=1
    volumes:
      - /app/seata/server1/application.yml:/seata-server/resources/application.yml
    networks:
      - seata_net

  seata2:
    image: seataio/seata-server:1.8.0
    container_name: seata2
    restart: always
    ports:
      - 7092:7092
      - 8092:8092
    environment:
      - SEATA_IP=192.168.136.128
      - SEATA_PORT=8092
      # 服务节点
      - SERVER_NODE=2
    volumes:
      - /app/seata/server2/application.yml:/seata-server/resources/application.yml
    networks:
      - seata_net

  seata3:
    image: seataio/seata-server:1.8.0
    container_name: seata3
    restart: always
    ports:
      - 7093:7093
      - 8093:8093
    environment:
      - SEATA_IP=192.168.136.128
      - SEATA_PORT=8093
      # 服务节点
      - SERVER_NODE=3
    volumes:
      - /app/seata/server3/application.yml:/seata-server/resources/application.yml
    networks:
      - seata_net

 # 网络配置
networks:
  seata_net:
    driver: bridge

这里需要说明的是:由于 docker 内部的 seata 服务,注册到 nacos 时使用的是 docker 内部的 ip 和端口,这样导致我们外部的 IDEA 代码无法访问。为了能够在后续的博客中,使用 IDEA 开发的 Demo 代码顺利访问 Seata,所以在 3 个节点的 Seata 服务中,设置环境变量 SEATA_IP 和 SEATA_PORT 为虚拟机的 ip 和映射出来的数据端口。

最后在虚拟机的 /app/seata 目录下,运行 docker-compose up -d 命令启动服务即可。


三、验证部署结果

  1. 可以在 /app/seata 目录下,使用如下命令查看每个节点的日志,看是否正常启动:
docker logs -f seata1
docker logs -f seata2
docker logs -f seata3
  1. 可以访问以下地址,看是否可以访问 seata 的 web 管理界面,登录账号和密码,我们配置的都是字符串 seata
http://192.168.136.128:7091
http://192.168.136.128:7092
http://192.168.136.128:7093

image

  1. 在 nacos 中查看 seata 服务的注册信息,看看是否是 3 个节点:

image

点击详情,可以查看注册的集群名称和节点信息,我们配置的集群名称是 jobs,三个节点采用虚拟机的 ip 和端口:

image


OK,以上就是 Seata 采用 docker-compose 搭建集群的过程。想要搭建单节点,只需要将 docker-compose.yml 中的其中 2 个节点的配置删掉即可。总体搭建过程比较简单。后面的博客将使用该环境,编写 demo 介绍如何使用 Seata 三种模式的分布式事务。

标签:Seata,lock,db,server,集群,mysql,分布式,seata
From: https://www.cnblogs.com/studyjobs/p/17845100.html

相关文章

  • 聊聊分布式 SQL 数据库Doris(一)
    MPPMPP:MassivelyParallelProcessing,即大规模并行处理.一般用来指多个SQL数据库节点搭建的数据仓库系统.执行查询的时候,查询可以分散到多个SQL数据库节点上执行,然后汇总返回给用户.DorisDoris作为一款开源的MPP架构OLAP高性能、实时的分析型数据库,能够运行在绝......
  • 分布式文件访问方案
    中心机房1.cpeh存储源站文件,利于横向扩展。2.7层负载均衡将分站访问分布在不同的nginx缓存服务器,分担访问。3.nginx使用proxy_cache将ceph的访问文件缓存到服务器的各块ssd硬盘,缓解ceph压力。分站机房1.app根据用户来源ip或者访问内容,将请求分布在不同分站2.分站的负......
  • Kubernetes Gateway API 攻略:解锁集群流量服务新维度!
    KubernetesGatewayAPI刚刚GA,旨在改进将集群服务暴露给外部的过程。这其中包括一套更标准、更强大的API资源,用于管理已暴露的服务。在这篇文章中,我将介绍GatewayAPI资源,并以Istio为例来展示这些资源是如何关联的。通过这个示例,你将了解GatewayAPI的各个组成部分如何配......
  • 分布式追踪的核心概念是 Trace 和 Span
    使用OpenTelemetry构建.NET应用可观测性(1):什么是可观测性  目录什么是系统的可观测性(Observability)为什么软件系统需要可观测性可观测性的三大支柱日志(Logging)指标(Metrics)分布式追踪(DistributedTracing)Trace和SpanUnknowUnknowsVSKnownUnknowns......
  • 分布式锁
    上一篇文章简单的介绍了单机的情况下如何进行加锁,防止高并发带来的问题。然而现实中,一般会高并发的应用,很少会单机部署。当用户量达到一定的程度,分布式、集群部署是必然的选择。在分布式部署的情况下,之前的单机锁还会有效吗?代码还是之前的代码:privatestaticobjectlck=n......
  • kubectl-切换集群
    kubectl远程调用k8s集群//当前集群信息kubectlcofingcurrent-context//当前集训配置信息kubectlconfigview//选择集群通过上下文名字切换kubectlcofinguse-contextcontextNAME .kube/config配置文件示例Cluster//待补充... ......
  • Redis之分布式锁
    前言日常开发中,秒杀下单、抢红包等等业务场景,都需要用到分布式锁。而Redis非常适合作为分布式锁使用。什么是分布式锁方案一:SETNX+EXPIRE方案二:SETNX+value值是(系统时间+过期时间)方案三:使用Lua脚本(包含SETNX+EXPIRE两条指令)方案四:SET的扩展命令(SETEXPX......
  • 分布式核心
    1.CAP理论cap理论是分布式系统的理论基石Consistency(一致性):“allnodesseethesamedataatthesametime”,即更新操作成功并返回客户端后,所有节点在同一时间的数据完全一致,这就是分布式的一致性。一致性的问题在并发系统中不可避免,对于客户端来说,一致性指的是并发访......
  • Hadoop学习(一) 搭建伪分布式集群
    文章结构1.准备工作1.1配置IP1.2关闭防火墙1.3修改主机名并与IP绑定1.4创建新用户1.5配置免密匙 2.安装并配置Hadoop伪分布式集群2.1安装Java2.2安装配置Hadoop伪分布式集群 1.准备工作1.1配置IP首先进入该路......
  • Apache Kylin4 分布式的分析型数据仓库
    https://kylin.apache.org/cn/docs/index.htmlApacheKylin4概述欢迎来到ApacheKylin™AnalyticalDataWarehouseforBigDataApacheKylin™是一个开源的、分布式的分析型数据仓库,提供Hadoop之上的SQL查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由eBayInc......