zl程序教程

您现在的位置是:首页 >  其他

当前栏目

mac 上学习k8s系列(53)seata-go

2023-02-18 16:32:25 时间

https://github.com/seata/seata-go是https://github.com/seata/seata的golang客户端,目前支持at和tcc两种分布式事务的实现。虽然官方的文档给的例子描述了如何处理分布式事务,但是如何部署和使用语焉不详。下面介绍下两种部署方式file、db

file模式是默认的模式性能最好,因为存在本地文件中,首先部署seata-server:

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#

version: '3'
services:
  seata-server:
    image: seataio/seata-server:1.5.2
    ports:
      - "8091:8091"
      - "7091:7091"
    environment:
      - SEATA_PORT=8091
      - STORE_MODE=file

  zookeeper:
    image: zookeeper
    ports:
      - "2181:2181"
    restart: on-failure

  mysql:
    image: mysql:5.7
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=12345678
    command: --default-authentication-plugin=mysql_native_password --default-time-zone='+08:00'
    volumes:
      - ./mysql:/docker-entrypoint-initdb.d
      - ./mysql/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
    ports:
      - "3306:3306"
docker compose -f seata-go/sample/dockercompose/docker-compose.yml up

然后运行我们的example

go run github.com/seata/seata-go/sample/at/basic

发现我们成功运行了

 127.0.0.1:3306)/seata_client, applicationData 
2022-12-10 21:23:49.510         INFO    getty/getty_remoting.go:79                      send async message: {message.RpcMessage{ID:3, Type:0x1, Codec:0x1, Compressor:0x0, HeadMap:map[string]string(nil), Body:message.BranchCommitResponse{AbstractBranchEndResponse:message.AbstractBranchEndResponse{AbstractTransactionResponse:message.AbstractTransactionResponse{AbstractResultMessage:message.AbstractResultMessage{ResultCode:0x1, Msg:""}, TransactionErrorCode:0}, Xid:"172.20.0.3:8091:27358463220736003", BranchId:27358463220736004, BranchStatus:5}}}}
2022-12-10 21:23:49.510         INFO    client/rm_branch_commit_processor.go:90         send branch commit success: xid 172.20.0.3:8091:27358463220736003, branchID 27358463220736004, resourceID root:12345678@tcp(127.0.0.1:3306)/seata_client, applicationData []

db模式相对复杂一些,我们需要修改配置

version: "3.1"
services:
  mysql:
    image: mysql:5.7
    container_name: mysql
    environment:
      - MYSQL_ROOT_PASSWORD=12345678
    command: --default-authentication-plugin=mysql_native_password --default-time-zone='+08:00'
    volumes:
      - ./mysql:/docker-entrypoint-initdb.d
      - ./mysql/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
    ports:
      - "3306:3306"
    extra_hosts:
     - host.docker.internal:host-gateway

  seata-server:
    image: seataio/seata-server:1.5.2
    ports:
      - "7091:7091"
      - "8091:8091"
    environment:
      - STORE_MODE=db
      # 以SEATA_IP作为host注册seata server
      # - SEATA_IP=host.docker.internal
      # - SEATA_PORT=8091
    volumes:
      # - "/usr/share/zoneinfo/Asia/Shanghai:/etc/localtime"        #设置系统时区
      # - "/usr/share/zoneinfo/Asia/Shanghai:/etc/timezone"  #设置时区
      # 假设我们通过docker cp命令把资源文件拷贝到相对路径`./seata-server/resources`中
      # 如有问题,请阅读上面的[注意事项]以及[使用自定义配置文件]
      - "./seata-server/resources/resources:/seata-server/resources"
    depends_on:
      - mysql
    extra_hosts:
     - host.docker.internal:host-gateway

其中,我们可以把配置文件拷贝出来修改下

docker cp 6df7f484515e:/seata-server/resources  ./seata-server/resources

修改后的application.yml如下:

server:
  port: 7091

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

console:
  user:
    username: seata
    password: seata

seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: file
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: file
  store:
    # support: file 、 db 、 redis
    mode: db
    db:
      datasource: druid
      dbType: mysql
      # 需要根据mysql的版本调整driverClassName
      # mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
      # mysql8以下版本的driver:com.mysql.jdbc.Driver
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://host.docker.internal:3306/seata_server?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
      user: root
      password: 12345678
      
  #  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,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

其中三点改动需要关注

1,- STORE_MODE=file改成了- STORE_MODE=db

2,地址需要改成host.docker.internal,原因在前面的系列文章中介绍过

3,dsn的数据库名需要改成seata_server

否则会报错

java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.

启动

docker compose -f docker-compose-db.yaml up

最后链接上mysql,创建我们依赖的库和表

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
create database `seata_server`;
use `seata_server`;

-- 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);

 create database seata_client;
 use seata_client;
 CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `commodity_code` varchar(255) DEFAULT NULL,
  `count` int(11) DEFAULT 0,
  `money` int(11) DEFAULT 0,
  `descs` varchar(255) DEFAULT "",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `money` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
mysql -uroot -p12345678 -h127.0.0.1 -e 'source mysql.sql'

需要注意的是,官方默认的数据库创建文件里少了个字段,导致跑不起来,需要加个字段

  CREATE TABLE `order_tbl`
  `descs` varchar(255) DEFAULT "",

启动我们的seata-go

 % go run github.com/seata/seata-go/sample/at/basic 

2022-12-10 22:13:05.384         INFO    client/rm_branch_commit_processor.go:90         send branch commit success: xid 172.19.0.3:8091:27358476928553095, branchID 27358476928553097, resourceID root:12345678@tcp(127.0.0.1:3306)/seata_client, applicationData []

发现已经成功了。

调试追踪过程中我们发现,会创建这种全局锁,事务完成后提交。

select * from global_table;
+-----------------------------------+-------------------+--------+----------------+---------------------------+-----------------------+---------+---------------+------------------+---------------------+---------------------+
| xid                               | transaction_id    | status | application_id | transaction_service_group | transaction_name      | timeout | begin_time    | application_data | gmt_create          | gmt_modified        |
+-----------------------------------+-------------------+--------+----------------+---------------------------+-----------------------+---------+---------------+------------------+---------------------+---------------------+
| 172.19.0.3:8091:27358476928553113 | 27358476928553113 |      1 | seata-go       | 127.0.0.1:8091            | ATSampleLocalGlobalTx |   30000 | 1670682517809 | NULL             | 2022-12-10 22:28:37 | 2022-12-10 22:28:37 |
+-----------------------------------+-------------------+--------+----------------+---------------------------+-----------------------+---------+---------------+------------------+---------------------+---------------------+
1 row in set (0.00 sec)