欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringCloudAlibaba技术栈学习(八)Seata分布式事务解决方案

程序员文章站 2022-03-26 15:01:55
第八章 Seata-分布式事务代码地址:源码地址1. 事务简介事务特性:A:原子性(Atomicity),一个事务中的所有操作,要么全部完成,要么全部不完成B:一致性(Consistency),在一个事务执行之前和执行之后数据库都必须处于一致性状态C:隔离性(Isolation),在并发环境中,当不同的事务同时操作相同的数据时,事务之间互不影响D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须永久的保存下来分布式架构下的事务问题:一个大事务下可能涉及到多个...

第八章 Seata-分布式事务

代码地址:源码地址

1. 事务简介

事务特性:
A:原子性(Atomicity),一个事务中的所有操作,要么全部完成,要么全部不完成
B:一致性(Consistency),在一个事务执行之前和执行之后数据库都必须处于一致性状态
C:隔离性(Isolation),在并发环境中,当不同的事务同时操作相同的数据时,事务之间互不影响
D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须永久的保存下来
分布式架构下的事务问题:一个大事务下可能涉及到多个微服务需要进行数据库操作,可能一个微服务操作成功,一个操作失败,不好保证事务的一致性,原子性。

2. 分布式事务解决方案

2.1 全局事务

需要三种角色:
AP: Application 应用系统 (微服务)
TM: Transaction Manager 事务管理器 (全局事务管理)
RM: Resource Manager 资源管理器 (数据库)
借用教程里的图片,教程地址:视频地址
SpringCloudAlibaba技术栈学习(八)Seata分布式事务解决方案
表决,执行

2.2 可靠消息服务

利用第六章说到的MQ事务消息,解决分布式事务问题。
SpringCloudAlibaba技术栈学习(八)Seata分布式事务解决方案
在第六章,我们实现的是order+user两个微服务的事务消息,这里再加一个product减库存的事务进去,实现步骤:
①在product模块创建service类,继承RocketMQListener<>泛型里填消息传来的对象类,Order
②添加注解RocketMQMessageListener指定监听的消息主题
③重写onMessage方法,实现减库存操作。代码如下:

@Service
@RocketMQMessageListener(
        consumerGroup = "shop-user"
        ,topic = "order-topic"
)
public class ReduceInventoryService implements RocketMQListener<Order> {
    @Autowired
    ProductService productService;
    @Override
    public void onMessage(Order order) {
        productService.reduceInventory(order.getPid(),order.getNumber());
    }
}

2.3 最大努力通知

2.4 TCC事务

Try,Confirm,Cancel类似于全局事务

3. Seata

3.1 Seata整合

①首先下载seata,下载地址
②修改配置,这部分由于各版本不同,修改的地方也不尽相同。大概就是把类型设置成nacos还有加入service.vgroup_mapping.service-order=default这种格式的配置,和微服务一一对应。
③初始化配置:

cd conf
nacos-config.sh 127.0.0.1

初始化完成后,可以在nacos的配置列表中看到很多seata的配置。
④启动seate

cd bin
seata-server.bat -p 9000 -m file

启动成功后可以在nacos的服务列表中看到seata的服务。serverAddr
⑤在数据库中创建表:

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;

⑥在微服务中引入依赖:

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

⑦在各个微服务的config包下编写配置类:

@Configuration
public class DataSourceProxyConfig {
	@Bean
	@ConfigurationProperties(prefix = "spring.datasource")
	public DruidDataSource druidDataSource() {
		return new DruidDataSource();
	} 
	@Primary
	@Bean
	public DataSourceProxy dataSource(DruidDataSource druidDataSource) {
		return new DataSourceProxy(druidDataSource);
	}
}

⑧把seata conf路径下的的registry.conf文件复制到各个微服务的resource包中。
⑨修改各个微服务的bootstrap文件,使其读取seata的配置。(这里微服务自己的配置不知道怎么放到nacos上去了,只能放在application.yml里面)

spring:
	application:
		name: service-product
	cloud:
		nacos:
			config:
				server-addr: localhost:8848 # nacos的服务端地址
				namespace: public
				group: SEATA_GROUP
		alibaba:
			seata:
				tx-service-group: ${spring.application.name}

⑩在事务的开始添加注解@GlobalTransactional即可利用seata完成分布式事务的处理。

3.2 Seata运行流程

把分布式事务看成微服务调用微服务的过程,在事务开始的地方注册了一个全局的XID,之后每条分支的XID都与之相等。
在微服务调用另一个微服务时,由被调用的微服务注册分支事务,产生一个BranchID,这个分支事务的BranchID是独一无二的,但是XID和这条链路上的其他分支一样。
分支事务之中undo_log和业务逻辑共同操作,undo_log记录业务逻辑操作数据库前后的状态。
当分支事务处理完后,会上报处理结果,由TC判断是否回滚,

本文地址:https://blog.csdn.net/qq_41109942/article/details/107573333