Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用

1,616 阅读5分钟

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

本文没有任何理论知识,纯操作步骤,包含以下内容:

  • 使用 docker-compose 部署 Seata Server 单节点
  • 使用 docker-compose 部署一台主机多个实例的 Seata Server 集群
  • 使用 Kubernetes 部署多主机的 Seata Server 集群

涉及到的软件版本:

软件名称版本号
Docker20.10.17
Docker Composev2.10.0
Rancherv2.5.2
Kubernetesv1.19
Seata1.4.2
Nacos2.0.3
MySQL8.0.29

Tip: 本文安装的 Seata Server 是以 Nacos 为注册中心,DB 为数据存储的模式。

按照本文的安装步骤安装,你大概率不会踩坑,因为坑已经被我踩过了:)

Docker 容器和外界网络连通性问题

为了防止 Docker 容器和外界网络无法连通,需要开启 IP 转发功能,步骤如下:

1, Linux系统缺省并没有打开IP转发功能,用如下命令确认IP转发功能的状态:

cat /proc/sys/net/ipv4/ip_forward

2, 如果发现该值为0,说明禁止进行IP转发;如果是1,则说明IP转发功能已经打开。打开IP转发功能命令:

echo 1 > /proc/sys/net/ipv4/ip_forward

3, 使配置生效

sysctl -p /etc/sysctl.conf

4, 重启网络 & Docker

systemctl restart network && systemctl restart docker

Tip: 如果不开启 ip_forward ,后面使用 Docker 安装 Seata Server 的时候,可能会因为连接不上 Nacos 而启动 Seata 失败。

使用 Docker Compose 部署 Seata Server 单节点

1, 在 MySQL 中,创建 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);

image-20220902215629586.png

2, 在 Nacos 配置中心,创建一个命名空间,名为 distributed-transaction

160e49b52dcf41b59fdee62167332b75.png

image-20220902220444299.png

命名空间名称没有要求,根据实际情况命名即可。

3, 在上一步的命名空间中,新建一个配置文件,dataId 为 seataServer.properties

image-20220902220800115.png

文件 seataServer.properties 内容为:

service.vgroupMapping.default_tx_group=default

# 存储模式
store.mode=db

store.db.datasource=druid
store.db.dbType=mysql

store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://192.168.242.112:3306/seata-server?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
store.db.user=zhangsan
store.db.password=Fawai@kuangtu6

4, 创建目录 /usr/local/seata/seata-config ,并在该目录下创建 registry.conf 文件:

registry {
  type = "nacos"
  
  nacos {
    application = "seata-server"
    serverAddr = "192.168.242.112:81"
    namespace = "5a4e4c1f-beda-4ae5-a3d7-428950e7473b"
    group = "SEATA_GROUP"
    cluster = "default"
    username = "nacos"
    password = "nacos123"
  }
}

config {
  type = "nacos"
  
  nacos {
    serverAddr = "192.168.242.112:81"
    namespace = "5a4e4c1f-beda-4ae5-a3d7-428950e7473b"
    group = "SEATA_GROUP"
    username = "nacos"
    password = "nacos123"
    dataId: "seataServer.properties"
  }
}

5,usr/local/seata 目录下创建 docker-compose.yml 文件,内容为:

version: "3"
services:
  seata-server:
    image: seataio/seata-server:1.4.2
    ports:
      - "8091:8091"
    environment:
      - SEATA_PORT=8091  
      - SEATA_IP=192.168.242.16
    volumes:
      - "./seata-config/registry.conf:/seata-server/resources/registry.conf"
    expose:
      - 8091
    container_name: seata-server

6,/usr/local/seata 目录下,执行如下命令启动:

docker-compose up

前面都准备好以后,只需要 docker-compose up -d-d 表示后台启动)这样一个命令就启动了 Seata Server 了:

image-20220905143424325.png

来看一下 Nacos 中有没有:

image-20220905142127299.png

OK,服务有了,我们可以点击详情进去看一下:

image-20220905142215214.png

使用 Docker Compose 部署 Seata Server 单机多实例集群

有了单节点部署的经验,部署单机多实例就很容易了,只需要修改一下 docker-compose.yml 文件,多加几个服务即可,这里以配置三个实例为例:

version: "3"
services:
  seata-server-1:
    image: seataio/seata-server:1.4.2
    hostname: seata-server
    ports:
      - "8091:8091"
    environment:
      - SEATA_PORT=8091
      - SEATA_IP=192.168.242.16
      - SEATA_CONFIG_NAME=file:/seata-server/resources/registry.conf
    volumes:
      - "./seata-config/registry.conf:/seata-server/resources/registry.conf"
  seata-server-2:
    image: seataio/seata-server:1.4.2
    hostname: seata-server
    ports:
      - "8092:8092"
    environment:
      - SEATA_PORT=8092
      - SEATA_IP=192.168.242.16
      - SEATA_CONFIG_NAME=file:/seata-server/resources/registry.conf
    volumes:
      - "./seata-config/registry.conf:/seata-server/resources/registry.conf"
  seata-server-3:
    image: seataio/seata-server:1.4.2
    hostname: seata-server
    ports:
      - "8093:8093"
    environment:
      - SEATA_PORT=8093
      - SEATA_IP=192.168.242.16
      - SEATA_CONFIG_NAME=file:/seata-server/resources/registry.conf
    volumes:
      - "./seata-config/registry.conf:/seata-server/resources/registry.conf"

当然了,各个文件的路径还是不能有差错的,目录结构如下:

image-20220905143317506.png

最后,还是在 /usr/local/seata 目录下,执行 docker-compose up

image-20220905143829383.png

再来看一下注册到 Nacos 中的 Seata Server 集群:

image-20220905143948511.png

image-20220905144016387.png

使用 K8S 快速部署 Seata Server 高可用集群

使用 K8S 部署 Seata Server 高可用集群非常简单,如果你的 K8S 是使用 Rancher 来部署的,那么在 Rancher 上使用 K8S 来部署应用将会简单乘以2,快乐加倍!

Rancher 的使用请看我的另一篇文章:使用Rancher部署管理K8S集群,真香!

下面我来演示一下在 Rancher 上如何快速部署 Seata Server,首先,准备一下需要的的 yaml 文件,内容如下:

apiVersion: v1
kind: Service
metadata:
  name: seata-ha-server
  namespace: default
  labels:
    app.kubernetes.io/name: seata-ha-server
spec:
  type: ClusterIP
  ports:
    - port: 8091
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: seata-ha-server

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: seata-ha-server
  namespace: default
  labels:
    app.kubernetes.io/name: seata-ha-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: seata-ha-server
  template:
    metadata:
      labels:
        app.kubernetes.io/name: seata-ha-server
    spec:
      containers:
        - name: seata-ha-server
          image: docker.io/seataio/seata-server:1.4.2
          imagePullPolicy: IfNotPresent
          env:
            - name: SEATA_CONFIG_NAME
              value: file:/root/seata-config/registry
            - name: SEATA_IP
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: status.hostIP
          ports:
            - name: http
              containerPort: 8091
              protocol: TCP
          volumeMounts:
            - name: seata-config
              mountPath: /root/seata-config
      volumes:
        - name: seata-config
          configMap:
            name: seata-ha-server-config


---
apiVersion: v1
kind: ConfigMap
metadata:
  name: seata-ha-server-config
data:
  registry.conf: |
    registry {
        type = "nacos"
        nacos {
          application = "seata-server"
          serverAddr = "192.168.242.112:81"
          namespace = "5a4e4c1f-beda-4ae5-a3d7-428950e7473b"
          group = "SEATA_GROUP"
          cluster = "default"
          username = "nacos"
          password = "nacos123"
        }
    }
    config {
      type = "nacos"
      nacos {
        serverAddr = "192.168.242.112:81"
        namespace = "5a4e4c1f-beda-4ae5-a3d7-428950e7473b"
        group = "SEATA_GROUP"
        username = "nacos"
        password = "nacos123"
        dataId: "seataServer.properties"
      }
    }

这里需要将 注册中心配置中心 改成自己的 Nacos 信息。

然后在 Rancher 面板上点击 导入 YAML

image-20220905114827909.png

将我们之前准备的内容复制进来:

image-20220905135702510.png

点击 导入 按钮后,Seata Server 集群将以不可思议的速度创建起来了:

image-20220905115217164.png

我们再看看 Nacos 注册中心中有没有 Seata Server 集群服务:

image-20220905115304279.png

那必须有啊,我用 Rancher 通过 K8S 部署服务没有失手过,哈哈!点击详情看一下集群信息:

image-20220905115435615.png

完美!