Day124.分布式事务:Seata、2PC两段式、代码补偿TCC、本地消息表、MQ事物消息
目录
一、相关概念回顾
二、分布式事务
三、分布式事务解决方案
1、基于XA协议的两段式提交(2PC) - 强一致性
2、代码补偿事务(TCC) - 最终一致性
3、本地消息表(异步确保)- 最终一致性
4、MQ 事务消息
5、Seata介绍
全局锁、本地锁,二段式提交
四、Seata案例初始化
五、Seata 原理
一、相关概念回顾
什么是事物:提供一种“要么什么都不做,要么做全套(All or Nothing)”机制。保证数据一致性
- 事务的四大属性?(ACID属性) ★
(1)原子性(Automicity)
事务中的操作要么都发生,要么都不发生。关系型事物才有,非关系型数据库缺点:没有强一致性
(2)一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。(3)隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。事物间相互不影响
(4)持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响
- 事物(并发)操作中的问题?(针对隔离性) ★
脏读:一个事务读取了另一个事务未提交数据;
不可重复读:同一个事务中前后两次读取同一条记录不一样。因为被其他事务修改了并且提交了。(同一事务中查询的数据应保持一致性)
幻读:一个事务读取了另一个事务新增、删除的记录情况,记录数不一样,像是出现幻觉。
- 事物的四种隔离级别是?(一致性和并发性:一致性越好,并发性越差) ★
mysql默认的事务隔离级别为repeatable-read,mysql中使用了MVCC多版本控制技术,在这个级别也可以避免幻读。
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read-uncommitted) | √ | √ | √ |
读已提交(read-committed) | × | √ | √ |
可重复读(repeatable-read) | × | × | √ |
串行化(serializable) | × | × | × |
- 事物传播行为
名称 | 含义 |
---|---|
REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是默认值。 |
REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
NESTED | 如当前存在事务,则在嵌套事务内执行。如当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作 |
- 本地事务
本地事务也称为 数据库事务 或 传统事务 (相对于分布式事务而言)。
特征:只针对本地事务,一个数据库。事务的执行结果保证ACID。会用到数据库锁。
二、分布式事务
单体应用的数据一致性由本地事务来保证。而当单体应用被拆分为微服务,每个独立的服务分别使用独立的数据源:每一个服务内部的数据一致性仍由本地事务来保证,整个业务层面的全局数据一致性要如何保障呢?
当内部无法解决。引入外部协调者,解决内部事物 (全局事务ID?)
本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
分布式系统:部署在不同节点上的系统通过网络交互来完成协同工作的系统。
分布式事务应用在哪些场景
- 电商系统中的下单扣库存
电商系统中,订单系统和库存系统是两个系统,一次下单的操作由两个系统协同完成
- 金融系统中的银行卡充值
在金融系统中通过银行卡向平台充值需要通过银行系统和金融系统协同完成。
- 教育系统中下单选课业务
在线教育系统中,用户购买课程,下单支付成功后学生选课成功,此事务由订单系统和选课系统协同完成。
- SNS系统的消息发送
在社交系统中发送站内消息同时发送手机短信,一次消息发送由站内消息系统和手机通信系统协同完成。
跨多服务多数据库的分布式事务
三、分布式事务解决方案
1.XA两段提交(低效率)-分布式事务解决方案
2.TCC三段提交(2段,高效率[不推荐(补偿代码)])
3.本地消息(MQ+Table) (电商选择)
4.事务消息(RocketMQ[alibaba])
5.Seata(alibaba) 两段式提交的优化
1、基于XA协议的两段式提交(2PC) - 强一致性
X/Open 组织(即现在的 Open Group )定义了分布式事务处理模型。
当一个事务跨多个节点时,为了保持事务的原子性与一致性,需要引入一个 协调者(Coordinator)来统一掌控所有 参与者(Participant) 的操作结果,并指示它们是否要把操作结果进行真正的提交(commit)或者回滚(rollback)
二阶段提交2PC(Two phase Commit)是指,在分布式系统里,为了保证所有节点在进行事务提交时保持一致性的一种算法。
2PC顾名思义分为两个阶段,其实施思路可概括为:
(1)投票阶段(voting phase):参与者将操作结果通知协调者 (举例开会发邮件,需要回复)
(2)提交阶段(commit phase):收到参与者的通知后,协调者再向参与者发出通知,根据反馈情况决定各参与者是否要提交还是回滚;
缺陷:一个模块出现问题(没有反馈),所有模块都会阻塞。2PC遵循强一致性,效率很低。
XA协议:XA是一个分布式事务协议。XA中大致分为两部分:事务管理器和本地资源管理器。其中本地资源管理器往往由数据库实现,比如Oracle、DB2(IBM)这些商业数据库都实现了XA接口,而事务管理器作为全局的调度者,负责各个本地资源的提交和回滚。
2、代码补偿事务(TCC) - 最终一致性
XA是资源层面的分布式事务,强一致性。TCC通过代码补偿的方式,保证最终一致性。三段式事物,本质还是两段式。
具体流程:(飞机票)
TCC是Try ( 尝试 ) — Confirm(确认) — Cancel ( 取消 ) 的简称:
操作方法 | 含义 |
---|---|
Try | 完成所有业务检查(一致性),预留业务资源(准隔离性) 回顾上面航班预定案例的阶段1,机票就是业务资源,所有的资源提供者(航空公司)预留都成功,try阶段才算成功 |
Confirm | 确认执行业务操作,不做任何业务检查, 只使用Try阶段预留的业务资源。回顾上面航班预定案例的阶段2,美团APP确认两个航空公司机票都预留成功,因此向两个航空公司分别发送确认购买的请求。 |
Cancel | 取消Try阶段预留的业务资源。回顾上面航班预定 |
以航班预定的案例,从合肥 –> 昆明 –> 大理。
3、本地消息表(异步确保)- 最终一致性
- 订单系统新增一条消息表,将新增订单和新增消息放到一个事务里完成,然后通过轮询的方式去查询消息表,将消息推送到 MQ,库存系统去消费 MQ。
- 优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。
- 缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。
4、MQ 事务消息
有一些第三方的MQ是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交,但是市面上一些主流的MQ都是不支持事务消息的,比如 RabbitMQ 和 Kafka 都不支持。
RocketMQ提供了类似X/Open XA的分布事务功能,通过MQ的事务消息能达到分布式事务的最终一致。
半消息
总体而言RocketMQ事务消息分为两条主线
定时任务发送流程:发送half message(半消息),执行本地事务,发送事务执行结果
定时任务回查流程:MQ服务器回查本地事务,发送事务执行结果
半消息的实现,在RabbitMQ的基础上增加了功能
优点: 实现了最终一致性,不需要依赖本地数据库事务。
缺点: 目前主流MQ中只有RocketMQ支持事务消息(需要买阿里的服务)。
5、Seata介绍
Seata 是阿里开源的一个分布式事务框架,能够让大家在操作分布式事务时,像操作本地事务一样简单。一个注解搞定分布式事务。
- 解决分布式事务问题,有两个设计初衷
- 对业务无侵入:即减少技术架构上的微服务化所带来的分布式事务问题对业务的侵入
- 高性能:减少分布式事务解决方案所带来的性能消耗
- Seata中有两种分布式事务实现方案,AT 及 TCC
- AT模式主要关注多 DB 访问的数据一致性,当然也包括多服务下的多 DB 数据访问一致性问题 2PC-改进
- TCC 模式主要关注业务拆分,在按照业务横向扩展资源时,解决微服务间调用的一致性问题
官网:Seata
AT模式(Automatic (Branch) Transaction Mode)
- Transaction Coordinator (TC):事务协调器,维护全局事务的运行状态,负责协调并决定全局事务的提交或回滚。(Seata)
- Transaction Manager(TM): 控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。(全局入口)
- Resource Manager (RM):资源管理器,负责本地事务的注册,本地事务状态的汇报(投票),并且负责本地事务的提交和回滚。(分布式服务)
- XID:一个全局事务的唯一标识
其中,TM是一个分布式事务的发起者和终结者,TC负责维护分布式事务的运行状态,而RM则负责本地事务的运行。
全局锁、本地锁,二段式提交
①整体机制
两阶段提交协议的演变:
- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 二阶段:
- 提交异步化,非常快速地完成。
- 回滚根据一阶段的 回滚日志 进行反向补偿。
②写隔离
- 一阶段本地事务提交前,需要确保先拿到 全局锁 。
- 拿不到 全局锁 ,不能提交本地事务。
- 拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。
tx1 二阶段全局提交,释放 全局锁 。tx2 拿到 全局锁 提交本地事务。
③读隔离
在数据库本地事务隔离级别 读已提交(Read Committed) 或以上的基础上,Seata(AT 模式)的默认全局隔离级别是 读未提交(Read Uncommitted)。
如果应用在特定场景下,必需要求全局的 读已提交 ,目前 Seata 的方式是通过 SELECT FOR UPDATE(排他锁) 语句的代理 读取数据时,不允许其他线程对此条数据进行修改。
四、Seata案例初始化
想用Seata,分布式事务中所有模块所对应的的数据库,都应该有一张UNDO_LOG表。用于存储相关操作,用于补偿式回滚。
版本声明:
nacos-server-1.4.2 + seata-server-1.4.2 + MySQL5.7 + Hoxton.SR9 + Alibaba2.2.6.RELEASE + SpringBoot2.3.2.RELEASE
1、复制项目,下载依赖,修改配置mysql地址
2、创建表
3、启动nacos -1.4.2 startup.cmd -m standalone
修改nacos mysql持久化
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=Asia/Shanghai
db.user=root
db.password=******
测试,出现分布式事务问题。
用户模块报错。订单产生,库存减少,但是金钱没有减少。
4、在配置中心增加配置:seataServer.properties、common.yml,详情参考课件(注意分组)
创建 seata142 数据库,导入表:global_table、branch_table、lock_table,参考脚本
5、新建dataId为seataServer.properties的配置,内容如下:
6、搭建TC服务器
- 下载地址:Seata
- 解压seata-server-1.4.2.zip安装,修改D:\Server\seata-server-1.4.2\conf\registry.conf设置TC 服务对应的注册中心和配置中心。 这里选择Nacos,
注意:dataId = "seataServer.properties",从nacos配置中心拉取配置。
registry {# file 、nacos 、eureka、redis、zk、consul、etcd3、sofatype = "nacos"nacos {application = "seata-server"serverAddr = "127.0.0.1:8848"group = "SEATA_GROUP"namespace = ""cluster = "default"username = "nacos"password = "nacos"}
}
config {# file、nacos 、apollo、zk、consul、etcd3type = "nacos"nacos {serverAddr = "127.0.0.1:8848"namespace = ""group = "SEATA_GROUP"username = "nacos"password = "nacos"dataId = "seataServer.properties"}
}
- 进入到D:\Server\seata-server-1.4.2\bin目录运行seata-server.bat
7、引入seata依赖
在fescar-api项目中引入依赖,排除低版本依赖,重新引入1.4.2;传递给其他微服务项目使用。
<!--Seata依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.4.2</version>
</dependency>
8、fescar-api 工程下面新建配置类
@Configuration
public class DataSourceProxyConfig {/*** 普通数据源* @return*/@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource dataSource() {return new DruidDataSource();}/*** 代理数据源绑定DataSourceProxy ---> undo_log的操作* @param dataSource* @return*/@Beanpublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}/*** mybatis--->手动指定sqlSessionFactory所使用的代理数据源* @param dataSourceProxy* @return* @throws Exception*/@Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 换成代理数据源sqlSessionFactoryBean.setDataSource(dataSourceProxy);return sqlSessionFactoryBean.getObject();}
}
9、入口方法上添加@GlobalTransactional开启全局事务
测试:http://localhost:18081/business/addorder
记录了log日志,事务完成了回滚
五、Seata 原理
再看TC/TM/RM三大组件
- TM开启分布式事务(TM向TC注册全局事务记录)
- 换业务场景,编排数据库,服务等事务内资源(RM向TC汇报资源准备状态)
- TM结束分布式事务,事务一阶段结束(TM通知TC提交/回滚分布式事务)
- TC汇总事务信息,决定分布式事务是提交还是回滚
- TC通知所有RM提交/回滚资源,事务二阶段结束。
第一阶段加载
- 在一阶段,Seata会拦截"业务SQL"
- 1.解析SQL语义,找到“业务SQL”要更新的业务数据,在业务数据被更新前,将其保存成“before image”
- 2.执行"业务SQL"更新业务数据,在业务数据更新之后,
- 3.其保存成“after image”,最后生成行锁。
- 以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
二阶段提交
- 二阶段如果顺利提交的话,因为“业务SQL”在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
二阶段回滚
二阶段如果是回滚的话,Seata就需要回滚一阶段执行的“业务SQL”,还原业务数据。回滚方式便是用“before image”还原业务数据;但在还原前要首先校验脏写,对比“数据库当前业务数据”和“after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
Day124.分布式事务:Seata、2PC两段式、代码补偿TCC、本地消息表、MQ事物消息相关推荐
- 多个mapper的事务回滚_揭秘蚂蚁金服分布式事务 Seata 的AT、Saga和TCC模式
作者| 屹远(陈龙),蚂蚁金服分布式事务核心研发 . 导语 本文根据 8月11日 SOFA Meetup#3 广州站 <分布式事务 Seata 及其三种模式详解>主题分享整理,着重分享分布 ...
- 探秘蚂蚁金服分布式事务 Seata 的AT、Saga和TCC模式
作者| 屹远(陈龙),蚂蚁金服分布式事务核心研发 . 导语 本文根据 SOFA Meetup#3 广州站 <分布式事务 Seata 及其三种模式详解>主题分享整理,着重分享分布式事务产生的 ...
- 关于分布式事务、2pc两阶段提交协议、3pc三阶提交协议
本文转载自:https://mp.weixin.qq.com/s/87-znh7Q-SvQfF9u8O3Trg 随着大型网站的各种高并发访问.海量数据处理等场景越来越多,如何实现网站的高可用.易伸缩. ...
- 分布式事务:XA,2PC,3PC,TCC,SEATA(AT)
一.分布式事务产生原因 1.原本的数据是单库单表存储,随着业务的不断扩大数据量不断增多,单库性能支撑不了数据的更新与访问.为了解决数据库上的瓶颈,将数据库进行水平拆分,原来一个库里的事务操作,现在变成 ...
- 分布式事务Seata的AT模式下两阶段提交原理
文章目录 第一阶段 1. 扫描@GlobalTransactional注解,获取全局事务XID 2. TC生成全局事务XID,记录入库 3. 执行业务逻辑,提交本地事务,记录branch_table. ...
- 什么是分布式事务Seata?Seata的几种事务模式详解
最后更新于:2020-04-08 17:37 目录 概念 发展历程 核心组件 三种事务模式 AT模式 前提 一个分布式事务在Seata中的执行流程 Seata 的事务提交方式与 XA 协议的两段式提交 ...
- 分布式事务Seata框架的AT模式
大纲 分布式事务 seata架构 1.分布式事务 在分布式系统架构中,复杂的业务需要跨库操作,要保证全局的事务一致性问题就得需要解决分布式事务问题. 1.1 XA规范 XA规范中,规定了三种角色:AP ...
- 分布式事务 Seata
目录 分布式事务 产生原因 CAP定理 BASE理论 分布式事务解决思路 2pc&3pc Seata Seata架构 四种方案 部署TC服务器 微服务集成Seata XA模式 XA规范 Sea ...
- 面试被问分布式事务(2PC、3PC、TCC),这样解释没毛病!
絮絮叨叨 还记得刚入行开始写Java时,接触的第一个项目是国家电网的一个业务系统,这个系统据说投资了5亿人民币进行研发,鼎盛时期研发人员一度达到过500人.项目采用当时最流行的ssh(Struts+S ...
最新文章
- C语言高级编程:函数指针的用法
- 使用 Bridge to Kubernetes 简化云端开发
- mysql 忘记密码
- malloc和free
- 微信iOS版朋友圈可删除评论;周鸿祎:有的软件会偷拍偷录;银河麒麟操作系统V10发布| 极客头条
- MIT脑洞研究!只听6秒语音,就知道你长什么样,效果好得不敢信
- 创建LEANGOO账号
- [转] 做一个让人欣赏的女子
- Iptables基本概念及应用
- 编译DPDK遇到make: *** /lib/modules/3.10.0-693.el7.x86_64/build: no such file or dirortory
- 黑马程序员2022年最新软件测试学习路线
- Mysql蜜罐读取电脑配置文件
- 提高IT团队工作效率的建议
- WIN10插上耳机拔掉后再插没声音的问题【已解决】
- 不定积分、定积分的区别与联系
- 什么是“富人思维”?
- matlab在量子力学中的应用,一个关于量子力学中的matlab的问题
- 前端学HTTP之web攻击技术
- 【JVM调优工具】JVM调优工具
- freemind 要下载java_FreeMind下载、安装及使用介绍
热门文章
- 解决RuntimeError: stack expects a non-empty Tensorlist问题
- 【opencv 450 core】使用统一向量指令(Universal Intrinsics)对代码进行矢量化
- Mybatis中的大于、小于、大于等于、小于等于、不等于的两种写法
- 微信客户管理方式及如何微信客户管理
- MySQL初级篇——存储过程、存储函数的相关概念及应用举例
- Maltrail恶意流量检测系统
- 小米有品众筹仅249!Oclean X智能触屏电动牙刷6日劲爆开抢
- visual studio code打开预览.md文件
- ROS2—小海龟仿真器基础使用
- 将一串整数转化为一串字符