SpringCloudAlibaba技术栈学习(八)Seata分布式事务解决方案
第八章 Seata-分布式事务
代码地址:源码地址
1. 事务简介
事务特性:
A:原子性(Atomicity),一个事务中的所有操作,要么全部完成,要么全部不完成
B:一致性(Consistency),在一个事务执行之前和执行之后数据库都必须处于一致性状态
C:隔离性(Isolation),在并发环境中,当不同的事务同时操作相同的数据时,事务之间互不影响
D:持久性(Durability),指的是只要事务成功结束,它对数据库所做的更新就必须永久的保存下来
分布式架构下的事务问题:一个大事务下可能涉及到多个微服务需要进行数据库操作,可能一个微服务操作成功,一个操作失败,不好保证事务的一致性,原子性。
2. 分布式事务解决方案
2.1 全局事务
需要三种角色:
AP: Application 应用系统 (微服务)
TM: Transaction Manager 事务管理器 (全局事务管理)
RM: Resource Manager 资源管理器 (数据库)
借用教程里的图片,教程地址:视频地址
表决,执行
2.2 可靠消息服务
利用第六章说到的MQ事务消息,解决分布式事务问题。
在第六章,我们实现的是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