Seata 2.x 系列【9】事务会话存储模式

有道无术,术尚可求,有术无道,止于术。

本系列Seata 版本 2.0.0

本系列Spring Boot 版本 3.2.0

本系列Spring Cloud 版本 2023.0.0

源码地址:https://gitee.com/pearl-organization/study-seata-demo

1. 概述

TC(服务端)作为事务协调者,负责维护全局和分支事务的状态,驱动全局事务提交或回滚。在一次全局事务(分布式事务)会话中,TC需要维护一些会话数据(事务状态和记录),比如全局事务信息分支事务信息锁信息等。

TC端的作用是保证事务的二阶段被正确执行,这取决于事务记录的正确存储。为确保事务记录不丢失,需要在保持状态正确的前提下,驱动所有的RM执行正确的二阶段行为。

2. 存储模式

Seata服务端支持多种方式存储会话数据:

  • file:本地文件(不支持HA
  • db:数据库(支持HA
  • redis:缓存数据库(支持HA
  • raft:服务端Raft算法实现(支持HA

模式类型配置说明:

配置项 描述 备注 版本说明
tore.mode 存储方式 filedbredisraft 1.5.1 版本改用 locksession 分离存储,2.0.0 开始支持raft模式
store.lock.mode 事务锁信息存储方式 filedbredis,配置为空时,取 store.mode 配置项值,raft 模式不允许单独指定 1.5.1 版本新增,sessionlock可分离存储
store.session.mode 事务会话信息存储方式 filedbredis,配置为空时,取 store.mode 配置项值,raft 模式不允许单独指定 1.5.1 版本新增,sessionlock可分离存储
store.publicKey dbredis 存储密码解密公钥 1.4.2 版本支持

Nacos控制台配置中心seata.properties文件中,可以看到默认使用的是file存储模式:
在这里插入图片描述

2.1 文件

file模式将会话数据存储在本地文件,以顺序写的形式将事务信息存储到本地磁盘上。为了兼顾性能,默认采用异步方式,并将事务信息存储在内存中,确保内存和磁盘上的数据一致性。当TC意外宕机时,在重新启动时会从磁盘读取事务信息并恢复到内存中,以便继续运行事务上下文。

file模式速度快,但是无法实现会话共享,所以不支持集群模式。

file模式下配置说明:

配置项 描述 备注
store.file.dir 存储文件夹名 默认 sessionStore
store.file.maxBranchSessionSize 分支 session 最大字节数 默认 16384(16kb),单位 byte
store.file.maxGlobalSessionSize 全局 session 最大字节数 默认 512b,单位 byte
store.file.fileWriteBufferCacheSize buffer 最大缓存大小 默认 16384(16kb),单位 byte,写入 session 等数据量大于该值时会抛出异常
store.file.flushDiskMode 刷盘策略 默认 async,可选 sync
store.file.sessionReloadReadSize Server 节点重启后从备份文件中恢复的 session lock key 上限个数 默认100

配置文件内容如下:
在这里插入图片描述
可以看到,在执行全局事务后,会在seata\bin\file_store\data\8091文件夹下生成一个root.data文件:
在这里插入图片描述

2.2 数据库

db模式采用数据库存储会话信息,依赖于数据库,在数据库中进行事务信息的增删改查操作。一致性由数据库的本地事务保证,数据也由数据库负责持久化到磁盘。基于计算和存储分离的架构设计。

db模式支持mysqloracledb2sqlserversybaeeh2sqliteaccesspostgresqloceanbase等数据库。支持集群,但是需要同步数据结构,依赖数据库,性能也不太高。

将存储模式改为db
在这里插入图片描述
db模式下配置说明:

配置项 描述 备注
store.db.datasource 数据源类型 支持dbcpdruidhikari ,无默认值
store.db.dbType 数据库类型 mysqloracledb2sqlserversybaeeh2sqliteaccesspostgresqloceanbase,无默认值
store.db.driverClassName 数据库驱动
store.db.url 数据库 url 在使用 mysql 作为数据源时,建议在连接参数中加上rewriteBatchedStatements=true(批量插入全局锁)
store.db.user 数据库账户
store.db.password 数据库账户密码
store.db.minConn 数据库初始连接数 默认 1
store.db.maxConn 数据库最大连接数 默认 20
store.db.maxWait 获取连接时最大等待时间 默认 5000,单位毫秒
store.db.globalTable 全局事务表名 默认 global_table
store.db.branchTable 分支事务表名 默认 branch_table
store.db.lockTable 全局锁表名 默认 lock_table
store.db.queryLimit 查询全局事务一次的最大条数 默认 100
store.db.distributedLockTable Sever 端事务管理全局锁存储表名 默认 distributed_lock,多 Sever 集群下保证同时只有一个 Sever 处理提交或回滚,1.5.1 版本新增

配置文件内容如下:
在这里插入图片描述
db模式下需要创建以下四张表:

  • global_table:全局事务表
  • branch_table:分支事务表
  • lock_table:全局锁表
  • distributed_lockSever事务管理全局锁存储表

seata\script\server\db目录提供了相关脚本:
在这里插入图片描述
官网SQL脚本没有注释,最好使用作者提供的:

-- seata_server.branch_table definition

CREATE TABLE `branch_table` (
  `branch_id` bigint NOT NULL COMMENT '分支事务ID',
  `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '全局事务唯一标识',
  `transaction_id` bigint DEFAULT NULL COMMENT '全局事务ID',
  `resource_group_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '资源分组ID',
  `resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '资源ID',
  `branch_type` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '事务模式',
  `status` tinyint DEFAULT NULL COMMENT '分支事务状态(io.seata.core.model.BranchStatus)',
  `client_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '客户端ID',
  `application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '应用数据',
  `gmt_create` datetime(6) DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime(6) DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`branch_id`),
  KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='分支事务会话表';

-- seata_server.global_table definition

CREATE TABLE `global_table` (
  `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '全局事务的唯一标识(IP+事务ID)',
  `transaction_id` bigint DEFAULT NULL COMMENT '全局事务ID',
  `status` tinyint NOT NULL COMMENT '全局事务状态(io.seata.core.model.GlobalStatus)',
  `application_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '应用ID(TM服务名)',
  `transaction_service_group` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '事务分组名',
  `transaction_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '开启事务类方法',
  `timeout` int DEFAULT NULL COMMENT '超时时间',
  `begin_time` bigint DEFAULT NULL COMMENT '开始时间',
  `application_data` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '应用数据',
  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`xid`),
  KEY `idx_status_gmt_modified` (`status`,`gmt_modified`),
  KEY `idx_transaction_id` (`transaction_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='全局事务会话表';

-- seata_server.lock_table definition

CREATE TABLE `lock_table` (
  `row_key` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '行键',
  `xid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '全局事务唯一标识',
  `transaction_id` bigint DEFAULT NULL COMMENT '全局事务ID',
  `branch_id` bigint NOT NULL COMMENT '分支ID',
  `resource_id` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '资源ID',
  `table_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '表名',
  `pk` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '主键对应的值',
  `status` tinyint NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking锁状态(0,已加锁;1,回滚中)',
  `gmt_create` datetime DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
  PRIMARY KEY (`row_key`),
  KEY `idx_status` (`status`),
  KEY `idx_branch_id` (`branch_id`),
  KEY `idx_xid` (`xid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='全局锁信息表';

-- seata_server.distributed_lock definition

CREATE TABLE `distributed_lock` (
  `lock_key` char(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '锁键',
  `lock_value` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '锁值',
  `expire` bigint DEFAULT NULL COMMENT '过期时间',
  PRIMARY KEY (`lock_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Sever事务管理全局锁存储表';

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.3 Redis

redis模式采用缓存数据库redis会话信息,是Seata 1.4 以后支持的新模式。和db 类似,也是一种事务存储方式,利用 JedisLua 脚本来进行事务的增删改查操作,部分操作(如竞争锁)在 Seata 2.x 版本中全部采用了Lua脚本。也依赖于存储方Redis来保证数据的一致性。基于计算和存储分离的架构设计。

redis模式的优点是支持集群,效率较快, 无需要同步数据结构。

将存储模式改为redis
在这里插入图片描述
db模式下配置说明:

配置项 描述 备注 版本说明
store.redis.mode 部署模式 默认 single,可选 sentinel 1.4.2 版本新增 sentinel 模式
store.redis.single.host 主机地址 单机模式下 redis host,兼容 1.4.2 之前的版本,该配置为空时选取 store.redis.host 作为配置项 1.4.2 版本新增
store.redis.single.port 端口 单机模式下 redisport,兼容 1.4.2 之前的版本,该配置为空时选取 store.redis.port 作为配置项 1.4.2 版本新增
store.redis.sentinel.masterName sentinel 模式下 redis 的主库名称 1.4.2 版本新增
store.redis.sentinel.sentinelHosts sentinel 模式下 sentinelhost hosts 以逗号分隔 1.4.2 版本新增
store.redis.host ip 默认 127.0.0.1 1.4.2 版本弃用
store.redis.port 端口 默认 6379 1.4.2 版本弃用
store.redis.maxConn 最大连接数 默认 10
store.redis.minConn 最小连接数 默认 1
store.redis.database 默认库 默认 0
store.redis.password 密码(无可不填) 默认 null
store.redis.queryLimit 一次查询最大条数 默认 100
store.redis.type 主要使用的方式: luapippline pippline

2.4 Raft

Raft官网地址
Seata-Raft 存储模式详解及入门

Raft是一种用于分布式场景下的一致性算法,Seata 2.0开始支持,提供了存算一体的高性能易扩展,入门门槛低,运维成本低等特定的事务存储模式。

Seata-Raft模式的设计思路是通过封装无法高可用的file模式,利用Raft算法实现多个TC之间数据的同步。该模式保证了使用file模式时多个TC的数据一致性,同时将异步刷盘操作改为使用Raft日志和快照进行数据恢复。

注意:

  • 😶😶😶但是目前基于Raft模式的解决方案可能还不够成熟,生产环境切勿使用。😶😶😶
  • 🤫🤫🤫不支持与第三方注册中心搭配,故全链路只允许存在一个TC集群🤫🤫🤫

将存储模式改为raft
在这里插入图片描述
raft模式下配置说明:

配置项 描述 备注 版本说明
server.raft.group 分组,client 的事务分组对应的值要与之对应,如 service.vgroup-mapping.default_tx_group=default 默认default 2.0.0 版本新增
server.raft.server-addr 集群列表 2.0.0 版本新增
server.raft.snapshot-interval 间隔多久做一次内存快照,每做一次快照将暂停状态机,但是能提高停机恢复速度 默认 600 2.0.0 版本新增
server.raft.apply-batch 任务累积批次后提交至 leader 默认 32 2.0.0 版本新增
server.raft.max-append-bufferSize raft 日志存储缓冲区最大大小 默认 256K 2.0.0 版本新增
server.raft.max-replicator-inflight-msgs 在启用 pipeline 请求情况下,最大 in-flight 请求数 默认 256 2.0.0 版本新增
server.raft.disruptor-buffer-size 内部 disruptor buffer 大小,如果是写入吞吐量较高场景,需要适当调高该值 默认 16384 2.0.0 版本新增
server.raft.election-timeout-ms 超过多久没有 leader 的心跳开始重选举 默认 1000 毫秒 2.0.0 版本新增
server.raft.reporter-enabled raft 自身的监控是否开启 默认 false 2.0.0 版本新增
server.raft.reporter-initial-delay 监控输出间隔 默认 60 2.0.0 版本新增
server.raft.serialization 序列化方式,目前仅支持 jackson 默认 jackson 2.0.0 版本新增
server.raft.compressor raftlogsnapshot 的压缩方式,支持 gzip, zstd, lz4 none 2.0.0 版本新增
server.raft.sync raftlog 同步刷盘 true 2.0.0 版本新增

配置文件内容如下:
在这里插入图片描述
Seata服务端需要修改注册中心为file

seata:
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos# 该配置可以选择不同的配置中心
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: file # raft模式下不允许使用非file的其他注册中心
  store:
    # support: file 、 db 、 redis 、 raft
    mode: raft # 使用raft存储模式
    file:
      dir: sessionStore # 该路径为raftlog及事务相关日志的存储位置,默认是相对路径,最好设置一个固定的位置

Seata客户端事务分组对应的TC集群需要修改为和server.raft.group 一致,并修改注册中心类型为raft
将tc集群改为server的raft group

seata:
   tx-service-group: default_tx_group
   service:
      vgroup-mapping:
         default_tx_group: 如果server.raft.group为default,那么此处便是default
   registry:
      type: raft
      raft:
         server-addr: 192.168.0.111:7091, 192.168.0.112:7091, 192.168.0.113:7091

3. 选型方案

Seata当前已经趋于成熟,性能入门门槛部署运维成本是未来发展的重点方向。

3.1 高可用

除了file模式外,dbredisraft模式都支持高可用集群部署。

3.2 一致性

一致性排名如下(由高到低):

  • raft:基于raft一致性算法
  • db:基于数据库事务
  • file:基于异步刷盘
  • redis:基于RDBAOF持久化

3.3 性能

性能排名如下(由高到低):

  • file:基于直接内存
  • redis:基于内存数据库
  • raft:基于raft
  • db:基于数据库

3.4 部署运维成本

部署运维成本排名如下(由高到低):

  • file:默认方式,直接部署即可
  • raft:只需修改配置,无需注册中心
  • redis:依赖于内存数据库,生产环境需要部署注册中心
  • db:基于数据库,需要同步数据接口,生产环境主要部署注册中心

3.5 成熟度

除了新出的raft模式,其他的基本已经很成熟,生产可用。

3.6 总结

raft模式是最理想的方案,但是当前并不成熟,所以不用考虑。

file模式简单易用,但是只支持单机模式部署,生产环境不考虑。

redisdb模式都支持集群部署,redis更易使用,且性能更高,所以推荐redis模式。

相关推荐

  1. Seata分布式事务

    2024-03-15 18:54:05       62 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-15 18:54:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-15 18:54:05       106 阅读
  3. 在Django里面运行非项目文件

    2024-03-15 18:54:05       87 阅读
  4. Python语言-面向对象

    2024-03-15 18:54:05       96 阅读

热门阅读

  1. 小米消金坚持打防并举,持续筑牢反诈坚实堤坝

    2024-03-15 18:54:05       35 阅读
  2. C++ 智能指针的正确使用方式:unique_ptr VS shared_ptr

    2024-03-15 18:54:05       34 阅读
  3. k8s的pod服务升级,通过部署helm升级

    2024-03-15 18:54:05       43 阅读
  4. axios 请求 url 地址,判断网络地址是否存在

    2024-03-15 18:54:05       42 阅读
  5. 面试经典-26-Z 字形变换

    2024-03-15 18:54:05       42 阅读
  6. mysql统计数据库大小

    2024-03-15 18:54:05       40 阅读
  7. TCP客户端发送结构体数据

    2024-03-15 18:54:05       39 阅读
  8. 数仓开发之ODS层

    2024-03-15 18:54:05       47 阅读
  9. 微信小程序canvas画布不清晰解决方法

    2024-03-15 18:54:05       43 阅读
  10. PyMySQL

    2024-03-15 18:54:05       41 阅读
  11. 设置docker和docker容器开机自启

    2024-03-15 18:54:05       42 阅读
  12. C语言(数组)单元练习二

    2024-03-15 18:54:05       38 阅读