分布式事务解决方案学习
2PC(两阶段提交)
2PC即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段P(Prepare phase),提交阶段C(commit phase),2是指两个阶段
- 准备阶段 : 事务管理器给每一个参与者发生Prepare信息,每个数据库参与者在本地执行事务,并写入日志,这时事务还没有提交
- 提交阶段: 如果事务管理器收到了参与者失败的或者超时消息时,就给每一个参与者发生(Rollback)信息,反正发生提交(commit)信息,参与者根据事务管理器的消息执行提交或者回滚操作
解决方案 seata
Seata 是阿里开源的一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。
图片来源于官网http://seata.io/zh-cn/
seata把一个分布式事务理解成一个包含若干分支事务和全局事务,全局事务的职责是协调其下管理的分支事务达成一致,要么一起成功提交,要么一起失败回滚
seata定义了3个组件来协调分布式事务的处理过程
-
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。 -
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。 -
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
比如现在有一个新用户注册送积分的seata的分布式事务过程
具体执行流程
- 用户服务的TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局的XID
- 用户服务的RM向TC注册分支事务,该分支事务在用户服务执行新增用户逻辑,并该分支事务纳入XID管辖
- 用户服务执行分支事务,向用户表插入一条记录
- 远程调用积分服务,由用户服务把XID下传播,积分服务的RM向TC注册分支事务,该分支事务在用户服务执行新增用户逻辑,并该分支事务纳入XID管辖
- 积分服务执行分支事务,向积分表插入一条记录
- 各分支事务执行完毕
- TM向TC发起针对该XID的提交或回滚决议
- TC调度XID其下的分支事务回滚或者提交
AT模式和XA模式
先看文档说明 图片来源官网
AT模式
自我总结理解:
-
XA模式:
需要传统事务配合,各个分支事务就是本地事务,各个分支事务执行后不提交也不回滚,把提交和回滚的事情交给TC事务协调者来做整体的事务回滚和提交 -
AT模式(工作中常用的一种):
不需要传统事务配合,执行后立马提交,并往undo_log表中写入一条记录数据(包含了修改前的数据和修改后的数据)TC事务协调者来做整体的事务回滚和提交的时候,如果是回滚操作,则根据undo_log表中的数据反向生成一条sql执行进行回滚随即删除undo_log的当条记录,如果是成功那么只需要删除undo_log的当条记录即完成了提交操作
AT案例实际操作
mysql安装(有数据库环境可忽略)
为简化安装步骤mysql采用docker的方式安装,如服务器没有docker环境请自行安装docker
链接: docker安装
进入Docker Hub 链接: Docker Hub
搜索我们需要的mysql镜像
找到mysql镜像
这里我们选择通用的5.7版本
拉取镜像
docker pull mysql:5.7
docker run --name some-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=这里写自己的密码 -d mysql:5.7
启动成功docker成功,我们来连接测试下
docker真的很方便两步操作mysql就搭建完了非常赞!
找到seata示例
代码地址 链接: https://github.com/seata/seata-samples
这里有seata很多的示例,就来试试spring-boot + mybatis的这个应该在项目中场景多点
示例说明
下载TC (Transaction Coordinator) - 事务协调者
运行bin下的bat文件即可
数据准备
修改配置文件
运行案例提供的sql
用户表数据
订单表数据
库存表数据
测试
启动各服务
案例给我们准备了成功和失败的接口
成功
在试试回滚代码,看到是在扣减账号后抛异常的
请求
明确的看到是在sql执行后才报错的
看到数据没有发生变化回滚成功
在报错之前打个断点来看看undo_log的数据是什么样的
这里看到了xid和他管辖的各分支事务id