十一. SpringCloud Alibaba (14)

从1:1 ⇒ 1:N ⇒ N:N,开始出现分布式事务问题

image-20210307121324123

分布式之后

单机应用被拆分成微服务应用,原来的三个模块被拆分成 三个独立的应用,分别使用 三个独立的数据源 ,业务操作需要调用 三个服务来完成。

此时 每个服务内部的数据一致性由 本地 事务来保证,但是 全局 的数据一致性问题没法保证

image-20210307121857129

一句话:一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题。

6.2 Seata简介

官网

下载地址

是什么

Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。

作用

一个典型的分布式事务过程:ID + 三组件模型

Transaction ID(XID):全局唯一的事务ID

三组件概念

Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚

Transaction Manager(TM):控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议

Resource Manage(RM):控制分支(本地)事务,负责分支注册,状态汇报,并接受事务协调的指令,驱动分支(本地)事务的提交和回滚

处理过程(我们可以用这种方式帮助理解:RM-学生,TM-班主任,TC-授课老师)

TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID

XID在微服务调用链路的上下文中传播

RM向TC注册分支事务,将其纳入XID对应全局事务的管辖

TM向TC发起针对XID的全局提交或回滚决议

TC调度XID下管辖的全部分支事务完成提交或回滚请求

image-20210307122934698

怎样用

本地 @Transational

全局 @GlobalTransational

seata的分布式交易解决方案

image-20210307123147388

6.3 Seata-Server安装

下载版本

修改conf目录下的file.conf配置文件

先备份原始file.conf文件

主要修改:自定义事务组名称 + 事务日志存储模式为db + 数据库连接

service模块 / store模块

image-20210307161625252

image-20210307150715252

mysql5.7数据库新建库seata,建表db_store.sql在seata-server-0.9.0\seata\conf目录里面

修改seata-server-0.9.0\seata\conf目录下的registry.conf目录下的registry.conf配置文件

目的是指明注册中心为nacos,及修改nacos连接信息。

image-20210307151534874

先启动Nacos,端口号为8848

再启动seata-server:bin目录下seata-server.bat

6.4 订单/库存/账户业务数据库准备

分布式事务业务说明

这里我们创建三个服务,一个订单服务,一个库存服务,一个账户服务。

当用户下单时,会在订单服务中创建一个订单,然后通过远程调用库存服务来扣减下单商品的库存,再通过远程调用账户服务来扣减用户账户里面的余额,最后在订单服务中修改订单状态为已完成。

该操作跨越三个数据库,有两次远程调用,很明显会有分布式事务问题。

创建业务数据库

建库sql

create database seata_order; create database seata_storage; create database seata_account;

按照上诉3库分别建立对应业务表

# seata_order库下新建t_order表 DROP TABLE IF EXISTS `t_order`; CREATE TABLE `t_order` ( `int` bigint(11) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) DEFAULT NULL COMMENT '用户id', `product_id` bigint(11) DEFAULT NULL COMMENT '产品id', `count` int(11) DEFAULT NULL COMMENT '数量', `money` decimal(11, 0) DEFAULT NULL COMMENT '金额', `status` int(1) DEFAULT NULL COMMENT '订单状态: 0:创建中 1:已完结', PRIMARY KEY (`int`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '订单表' ROW_FORMAT = Dynamic; # seata_storage库下新建t_storage表 DROP TABLE IF EXISTS `t_storage`; CREATE TABLE `t_storage` ( `id` bigint(11) NOT NULL AUTO_INCREMENT, `product_id` bigint(11) DEFAULT NULL COMMENT '产品id', `total` int(11) DEFAULT NULL COMMENT '总库存', `used` int(11) DEFAULT NULL COMMENT '已用库存', `residue` int(11) DEFAULT NULL COMMENT '剩余库存', PRIMARY KEY (`int`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '库存' ROW_FORMAT = Dynamic; INSERT INTO `t_storage` VALUES (1, 1, 100, 0, 100); # seata_account库下新建t_account表 CREATE TABLE `t_account` ( `id` bigint(11) NOT NULL COMMENT 'id', `user_id` bigint(11) DEFAULT NULL COMMENT '用户id', `total` decimal(10, 0) DEFAULT NULL COMMENT '总额度', `used` decimal(10, 0) DEFAULT NULL COMMENT '已用余额', `residue` decimal(10, 0) DEFAULT NULL COMMENT '剩余可用额度', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '账户表' ROW_FORMAT = Dynamic; INSERT INTO `t_account` VALUES (1, 1, 1000, 0, 1000);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpszdz.html