分布式事务seata集成和部署

727 阅读4分钟

环境准备

K8S环境(如果没有K8S环境,文中还提供了Docker的部署方式)

nacos地址:172.20.1.11:8848

postgres地址:172.20.1.11:5432

参考官方文档 

github.com/seata/seata…

Seata Server部署

1. 数据库准备

新建数据库seata

执行脚本

github.com/seata/seata…

-- the table to store GlobalSession data 
CREATE TABLE IF NOT EXISTS public.global_table
(
   xid                       VARCHAR(128) NOT NULL,
   transaction_id            BIGINT,
   status                    SMALLINT     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                TIMESTAMP(0),
   gmt_modified              TIMESTAMP(0),
   CONSTRAINT pk_global_table PRIMARY KEY (xid)
);

CREATE INDEX idx_gmt_modified_status ON public.global_table (gmt_modified, status);
CREATE INDEX idx_transaction_id ON public.global_table (transaction_id);

-- the table to store BranchSession data 
CREATE TABLE IF NOT EXISTS public.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            SMALLINT,
   client_id         VARCHAR(64),
   application_data  VARCHAR(2000),
   gmt_create        TIMESTAMP(6),
   gmt_modified      TIMESTAMP(6),
   CONSTRAINT pk_branch_table PRIMARY KEY (branch_id)
);

CREATE INDEX idx_xid ON public.branch_table (xid);

-- the table to store lock data 
CREATE TABLE IF NOT EXISTS public.lock_table
(
   row_key        VARCHAR(128) NOT NULL,
   xid            VARCHAR(96),
   transaction_id BIGINT,
   branch_id      BIGINT       NOT NULL,
   resource_id    VARCHAR(256),
   table_name     VARCHAR(32),
   pk             VARCHAR(36),
   gmt_create     TIMESTAMP(0),
   gmt_modified   TIMESTAMP(0),
   CONSTRAINT pk_lock_table PRIMARY KEY (row_key)
);

CREATE INDEX idx_branch_id ON public.lock_table (branch_id);

2.新建配置文件registry.conf

mkdir -p /data/seata
cd /data/seata
touch registry.conf 

输入

registry {

# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa

type = "nacos"

nacos {

 application = "seata-server"

 serverAddr = "172.20.1.11:8848"

 group = "DEFAULT_GROUP"

 namespace = "62821698-55ee-4b60-9bf3-bfc8eab0987f"

 cluster = "default"

 username = "nacos"

 password = "nacos"
}
}

config {

# file、nacos 、apollo、zk、consul、etcd3

type = "nacos"
nacos {

 serverAddr = "172.20.1.11:8848"

 group = "DEFAULT_GROUP" # 使用默认分组

 namespace = "62821698-55ee-4b60-9bf3-bfc8eab0987f"

 username = "nacos"

 password = "nacos"

}
}

3. 导入nacos配置

参考 

github.com/seata/seata…

git clone 下来,修改config.txt,这里删掉了部分配置,仅保留项目所需的。(请根据实际项目进行修改)

# 修改事务组。注意:客户端接入时,在yml文件中配置的组需要和这里对应
service.vgroupMapping.seata_tx_group=default
# 修改seata服务访问地址。使用K8S,这里配置的是映射出来的虚拟地址
service.default.grouplist=172.20.1.11:8091
# 配置数据库
store.db.datasource=druid
store.db.dbType=postgresql
store.db.driverClassName=org.postgresql.Driver
store.db.url=jdbc:postgresql://172.20.1.11:5432/seata
store.db.user=username
store.db.password=password

将config.txt上传到Nacos配置中心

cd /seata/script/config-center/nacos
chmod +x nacos-config.sh
./nacos-config.sh -h 172.20.1.11 -p 8848 -g DEFAULT_GROUP -t 62821698-55ee-4b60-9bf3-bfc8eab0987f  -u nacos -w nacos

4. K8S部署seata server

4.1 新建命名空间

kubectl create ns cym

备注:如果使用默认的命名空间,此步骤可以省略。但是需同步修改seata-server.yaml中的namespace

4.2  新建配置文件seata-server.yaml

touch seata-server.yaml

输入

apiVersion: apps/v1  
kind: Deployment 
metadata:
 name: seata
 namespace: cym
spec:
 replicas: 1
 selector:
   matchLabels:
     app: seata
 template:
   metadata:
     labels:
       app: seata
   spec:
     tolerations:
       - key: node.kubernetes.io/not-ready
         effect: NoExecute
         tolerationSeconds: 10
       - key: node.kubernetes.io/unreachable
         operator: Exists
         effect: NoExecute
         tolerationSeconds: 10
     containers:
       - name: seata
         image: seataio/seata-server:1.3.0
         imagePullPolicy: "IfNotPresent"
         ports:
           - containerPort: 8091
         env:
           - name: SEATA_CONFIG_NAME
             value: file:/root/registry
         volumeMounts:
           - mountPath: /dev/shm
             name: cache-volume
           - mountPath: /root/registry.conf
             name: registry-conf
           - mountPath: /etc/localtime
             name: localtime
             readOnly: true
     volumes:
       - emptyDir:
           medium: Memory
         name: cache-volume
       - name: registry-conf
         hostPath:
           path: "/data/seata/registry.conf"
       - name: localtime
         hostPath:
           path: "/etc/localtime"
     initContainers:
       - command:
         - sysctl
         - -w
         - net.ipv4.tcp_max_syn_backlog=8192
         image: busybox:1.32
         name: init-tcpmaxsyn
         securityContext:
           privileged: true
       - command:
         - sysctl
         - -w
         - net.core.somaxconn=8192
         image: busybox:1.32
         name: init-somaxconn
         securityContext:
           privileged: true
---
apiVersion: v1
kind: Service
metadata:
 name: seata
 namespace: cym
 labels:
   app: seata
spec:
 type: NodePort
 ports:
   - port: 8091
     targetPort: 8091
     nodePort: 8091  # nodePort默认30000-32767,请按实际情况 配置端口范围 或 修改此端口配置
 selector:
  app: seata

4.3. 启动seata server

kubectl apply -f seata-server.yaml 

4.4 查看部署结果

root@k8s-01:~# kubectl get pod -n cym 
NAME                        READY   STATUS    RESTARTS   AGE
seata-cym-77d49dcc4-kvrn7   1/1     Running   15         12d

附:Docker部署seata server

执行步骤1、2、3,略过4(K8S)

docker run --name seata-server \
-p 8091:8091 \
-e SEATA_CONFIG_NAME=file:/root/seata-config/registry \  # 容器内部文件
-v /data/seata:/root/seata-config \  # 容器外部目录:容器内部目录
--privileged=true \
-d seataio/seata-server:1.3.0

客户端集成Seata

准备spring boot项目,基于maven构建

1. 业务数据库

新增表undo_log。参考 

github.com/seata/seata…

CREATE TABLE IF NOT EXISTS public.undo_log
(
   id            SERIAL       NOT NULL,
   branch_id     BIGINT       NOT NULL,
   xid           VARCHAR(100) NOT NULL,
   context       VARCHAR(128) NOT NULL,
   rollback_info BYTEA        NOT NULL,
   log_status    INT          NOT NULL,
   log_created   TIMESTAMP(0) NOT NULL,
   log_modified  TIMESTAMP(0) NOT NULL,
   CONSTRAINT pk_undo_log PRIMARY KEY (id),
   CONSTRAINT ux_undo_log UNIQUE (xid, branch_id)
);

CREATE SEQUENCE IF NOT EXISTS undo_log_id_seq INCREMENT BY 1 MINVALUE 1 ;

2. pom.xml引入依赖

<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
   <version>2.2.3.RELEASE</version>
</dependency>

3. 修改yml配置文件

spring:
 cloud:
   nacos:
     discovery:
       server-addr: 172.20.1.11:8848
       namespace: 62821698-55ee-4b60-9bf3-bfc8eab0987f
     config:
       server-addr: 172.20.1.11:8848
       namespace: 62821698-55ee-4b60-9bf3-bfc8eab0987f
       file-extension: yml

seata:
 enabled: true
 application-id: ${spring.application.name}-seata # 不配置,默认使用spring服务名
 enable-auto-data-source-proxy: true
 tx-service-group: seata_tx_group  # 注意:必须和Seata server中配的分组一致
 config:
   type: nacos
   nacos:
     server-addr: 172.20.1.11:8848
     namespace: 62821698-55ee-4b60-9bf3-bfc8eab0987f
     group: DEFAULT_GROUP
 registry:
   type: nacos
   nacos:
     application: seata-server
     server-addr: 172.20.1.11:8848
     namespace: 62821698-55ee-4b60-9bf3-bfc8eab0987f
     group: DEFAULT_GROUP

4. 修改代码

在需要分布式事务的类方法上添加注解 

@GlobalTransactional(rollbackFor = Exception.class)

至此,完成seata的部署和spring boot的集成