目录
一、seata组件介绍
1、事务简介
2、本地事务(@Transational)
3、分布式事务
4、常见分布式事务解决方案
5、Seata使用教程
5.1、Seata介绍
5.2、Seata的三大角色
5.3、Seata快速开始
六、项目中集成Seata
1、添加pom.xml依赖
2、给微服务对应的数据库添加undo.log表(微服务中使用的数据库都需要添加undo.log表)
3、配置seata分组 (spring.cloud节点下)
4、配置seata service
5、在需要添加分布式事务的方法上添加注解
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成。事务应该具有4个属性:原子性、一致性、隔离性、持久性。 这四个属性通常称为ACID特性。
原子性(atomicity):个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么 都不做。
一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务 的中间状态不能被观察到的。
隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数 据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性又分为四个级别:读 未提交(read uncommitted)、读已提交(read committed,解决脏读)、可重复读(repeatable read,解决虚读)、串行化(serializable,解决幻读)。
持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库 中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务、分布式事务,及时不能 都很好的满足,也要考虑支持到什么程度。
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务
。本地事务的ACID特性是数据库直接提供支持。
当下互联网发展如火如荼,绝大部分公司都进行了数据库拆分和服务化(SOA)。在这种情况下,完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务,用需要操作的资源位于多个资源服务器上,而应用需要保证对于多个资源服务器的数据的操作,要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。
1、seata 阿里分布式事务框架
2、消息队列
3、saga
4、XA
他们有一个共同点,都是"两阶段(2PC)"。两阶段是指完成整个分布式事务,划分为两个步骤完成。实际上,这四种常见的分布式事务解决方案,分别对应着 四种分布式事务模式,都有各自的理论基础,分别在不同的时间被提出;每种模式都有它的适用场 景,同样每个模式也都诞生有各自的代表产品;而这些代表产品,可能就是我们常见的(全局事务、 基于可靠消息、最大努力通知、TCC)。
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)
官网:https://seata.io/zh-cn/index.html
源码: https://github.com/seata/seata
官方Demo: https://github.com/seata/seata-samples
在 Seata 的架构中,一共有三个角色:
TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
其中,TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端。
步骤一、下载安装包 :
https://github.com/seata/seata/releases
步骤二、修改seata配置,高可用
Server端存储模式(store.mode)支持三种:
file:(默认)单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
db:(5.7+)高可用模式,全局事务会话信息通过db共享,相应性能差些
打开config/file.conf
修改mode="db" 修改数据库连接信息(URL\USERNAME\PASSWORD)
创建数据库seata_server
新建表脚本:
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- 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);
修改conf文件夹下面的registry.conf文件,修改注册中心,配置中心为nacos,并完善nacos信息
修改script/config-center文件夹下config.txt,修改数据源信息、修改事务分组信息(解决机房异地停电、容错问题,每个服务指定调用哪一个分组 ,注意数据库驱动 8.0需要改为com.mysql.cj.jdbc.Driver)
service.vgroupMapping.default_tx_group=default
步骤三:导入配置进nacos
script/config-center/nacos文件夹下执行脚本nacos-conf.sh。
默认是在localhost:8848 默认命名空间 SEATA_GROUP分组,启动命令
sh nacos-config.sh
修改 ip(-h) 端口(-p) 名称空间(-t) 分组(-g),启动命令
sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t cbfe7aa0-a47c-4c42-80bc-3c0f9880413a
com.alibaba.cloud
spring-cloud-starter-alibaba-seata
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;
alibaba:
seata:
tx-service-group: shanxi #配置事务分组
seata:
# 配置seata注册中心,告诉微服务(seata client)怎么去访问seata server(TC)
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848 #seata server 所在的nacos服务地址
namespace: cbfe7aa0-a47c-4c42-80bc-3c0f9880413a
application: seata-server #seata server 的服务名 默认为seata-server 如果未修改可不配置
username: nacos #nacos username
password: nacos #nacos password
group: SEATA_GROUP #seata server 所在分组名称,默认是 SEATA_GROUP ,没有修改可以不配置
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848 #seata server 所在的nacos服务地址
namespace: cbfe7aa0-a47c-4c42-80bc-3c0f9880413a
username: nacos #nacos username
password: nacos #nacos password
group: SEATA_GROUP #seata server 所在分组名称,默认是 SEATA_GROUP ,没有修改可以不配置
@GlobalTransactional