兜兜零元 发表于 2024-10-27 05:23:33

分布式事务解决方案seata架构的安装摆设(AT模式)

1.介绍

seata官网:Seata 是什么? | Apache Seata
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简朴易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案
在Seata的事务管理中有三个紧张的脚色:


[*] TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
[*] TM (Transaction Manager) - 事务管理器:界说全局事务的范围、开始全局事务、提交或回滚全局事务。
[*] RM (Resource Manager) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
https://i-blog.csdnimg.cn/direct/6d95b21e99144b03935e443679c0b850.png
其中,TM和RM可以理解为Seata的客户端部分,引入到参与事务的微服务依赖中即可。将来TM和RM就会帮忙微服务,实现本地分支事务与TC之间交互,实现事务的提交或回滚。而TC服务则是事务协调中心,是一个独立的微服务,需要单独摆设。


https://i-blog.csdnimg.cn/direct/d80b7adf24b2422ca1d2e7d70dad1cd7.png
https://i-blog.csdnimg.cn/direct/ba119b8fe13a4453867981ed91b83959.png

2.摆设TC服务

2.1 导入数据库表

Seata支持多种存储模式,但考虑到持久化的需要,我们一般选择基于数据库存储。因此需要创建一个数据库‘seata’,运行一下sql命令。
CREATE DATABASE IF NOT EXISTS `seata`;
USE `seata`;


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;


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;


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_and_branch_id` (`xid` , `branch_id`)
) 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); 2.2.准备配置文件

创建一个seata文件夹,在该文件夹下创建一个application.yml文件,写入配置信息,例:
server:
port: 7099

spring:
application:
    name: seata-server

logging:
config: classpath:logback-spring.xml
file:
    path: ${user.home}/logs/seata
extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

seata:
config:
    # support: nacos 、 consul 、 apollo 、 zk、 etcd3
    type: file
    nacos:
      server-addr: 127.0.0.1:8848
      namespace:
      group: SEATA_GROUP
      username:
      password:
      data-id: seataServer.properties
    consul:
      server-addr: 127.0.0.1:8500
      acl-token:
      key: seata.properties
    apollo:
      appId: seata-server
      apollo-meta: http://192.168.1.204:8801
      apollo-config-service: http://192.168.1.204:8080
      namespace: application
      apollo-access-key-secret:
      cluster: seata
    zk:
      server-addr: 127.0.0.1:2181
      session-timeout: 6000
      connect-timeout: 2000
      username:
      password:
      node-path: /seata/seata.properties
    etcd3:
      server-addr: http://localhost:2379
      key: seata.properties
registry:
    # support: nacos 、 eureka 、 redis 、 zk、 consul 、 etcd3 、 sofa
    type: file
    preferred-networks: 30.240.*
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace:
      cluster: default
      username:
      password:
    eureka:
      service-url: http://localhost:8761/eureka
      application: default
      weight: 1
    redis:
      server-addr: localhost:6379
      db: 0
      password:
      cluster: default
      timeout: 0
    zk:
      cluster: default
      server-addr: 127.0.0.1:2181
      session-timeout: 6000
      connect-timeout: 2000
      username: ""
      password: ""
    consul:
      cluster: default
      server-addr: 127.0.0.1:8500
      acl-token:
    etcd3:
      cluster: default
      server-addr: http://localhost:2379
    sofa:
      server-addr: 127.0.0.1:9603
      application: default
      region: DEFAULT_ZONE
      datacenter: DefaultDataCenter
      cluster: default
      group: SEATA_GROUP
      address-wait-time: 3000

server:
    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
    max-commit-retry-timeout: -1
    max-rollback-retry-timeout: -1
    rollback-retry-timeout-unlock-enable: false
    enableCheckAuth: true
    retryDeadThreshold: 130000
    recovery:
      committing-retry-period: 1000
      asyn-committing-retry-period: 1000
      rollbacking-retry-period: 1000
      timeout-retry-period: 1000
    undo:
      log-save-days: 7
      log-delete-period: 86400000
store:
    # support: file 、 db 、 redis
    mode: file
    session:
      mode: file
    lock:
      mode: file
    file:
      dir: sessionStore
      max-branch-session-size: 16384
      max-global-session-size: 512
      file-write-buffer-cache-size: 16384
      session-reload-read-size: 100
      flush-disk-mode: async
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: mysql
      password: mysql
      min-conn: 5
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 100
      max-wait: 5000
    redis:
      mode: single
      database: 0
      min-conn: 1
      max-conn: 10
      password:
      max-total: 100
      query-limit: 100
      single:
      host: 127.0.0.1
      port: 6379
      sentinel:
      master-name:
      sentinel-hosts:
metrics:
    enabled: false
    registry-type: compact
    exporter-list: prometheus
    exporter-prometheus-port: 9898 本身更改端口号、nacos地址和数据库地址、暗码即可。将整个seata文件夹拷贝到假造机的/root目次
2.3 Docker摆设

需要注意,要确保nacos、mysql都在同一个Docker网络中。如果某个容器不在Docker网络,可以参考下面的命令将某容器加入指定网络:
docker network connect [网络名] [容器名] 可以使用以下命令检查某个容器在哪个网络,
docker inspect [容器名] 例如:我使用 docker inspect mysql ,,可以看到该容器在“elk”网络中
https://i-blog.csdnimg.cn/direct/acad6ca61b054016b54aa640506f36ad.png
在假造机的/root目次执行下面的命令:,将Docker网络和上面配置信息的ip地址改成本身对应的
docker run --name seata \
-p 8099:8099 \
-p 7099:7099 \
-e SEATA_IP=172.0.0.1 \
-v ./seata:/seata-server/resources \
--privileged=true \
--network elk \
-d \
seataio/seata-server:1.5.2 https://i-blog.csdnimg.cn/direct/7027b38c54ee46e297a6d5984b9ec5b4.png

安装完成后可以通过欣赏器访问127.0.0.1:1099 进入seata界面,初次登录账号暗码都是admin
https://i-blog.csdnimg.cn/direct/e978e662c16b46c18e6fe1c408473885.png
进入后可以看到事务的信息和一些锁的信息:
https://i-blog.csdnimg.cn/direct/4080b723e6f54ca69cc901545d519a94.png
3.微服务集成Seata

3.1 引入依赖

为了方便各个微服务集成seata,我们需要把seata配置共享到nacos,因此模块不仅仅要引入seata依赖,还要引入nacos依赖:
<!--统一配置管理-->
<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap文件-->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!--seata-->
<dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency> 3.2 改造配置

在nacos上添加一个共享的seata配置,命名为shared-seata.yaml
将nacos ip地址改成本身的
seata:
registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    type: nacos # 注册中心类型 nacos
    nacos:
      server-addr: 127.0.0.1:8848 # nacos地址 ,ip改成自己服务器地址
      namespace: "" # namespace,默认为空
      group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
      application: seata-server # seata服务名称
      username: nacos
      password: nacos
tx-service-group: hmall # 事务组名称
service:
    vgroup-mapping: # 事务组与tc集群的映射关系
      hmall: "default" 然后,改造模块,添加bootstrap.yaml
spring:
application:
    name: trade-service # 服务名称
profiles:
    active: dev
cloud:
    nacos:
      server-addr: 172.0.0.1:8848 # nacos地址
      config:
      file-extension: yaml # 文件后缀名
      shared-configs: # 共享配置
          - dataId: shared-jdbc.yaml # 共享mybatis配置
          - dataId: shared-log.yaml # 共享日志配置
          - dataId: shared-swagger.yaml # 共享日志配置
          - dataId: shared-seata.yaml # 共享seata配置 再改造application.yaml文件,将重复的部分删掉
3.3添加数据库

在涉及分布式事务的微服务的数据库中运行下面sql语句=>创建undo_log表格
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(
    `branch_id`   BIGINT       NOT NULL COMMENT 'branch transaction id',
    `xid`         VARCHAR(128) NOT NULL COMMENT 'global transaction id',
    `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
    `rollback_info` LONGBLOB   NOT NULL COMMENT 'rollback info',
    `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
    `log_created`   DATETIME(6)NOT NULL COMMENT 'create datetime',
    `log_modified`DATETIME(6)NOT NULL COMMENT 'modify datetime',
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
3.4实现方法:

在涉及分布式事务的业务代码上加上Seata提供的@GlobalTransactional注解即可
   @GlobalTransactional
在配置文件中指定要采用的分布式事务模式。我们可以在Nacos中的共享shared-seata.yaml配置文件中设置:
seata:
data-source-proxy-mode: XA
 JDK17运行报错可以见:JDK17运行seata发生报错Error creating bean with name ‘globalTransactionScanner‘的解决方案-CSDN博客

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 分布式事务解决方案seata架构的安装摆设(AT模式)