分布式事务概念及相关解决方案

有道云笔记
链接:http://note.youdao.com/noteshare?id=09430f22fb5cb732d048bc93159bf688

1,分布式事务产生的背景
在微服务环境下,因为会根据不同的业务会拆分成不同的服务,比如会员服务、订单服务、
商品服务等,让专业的人做专业的事情,每个服务都有自己独立的数据库,并且是独立运行,
互不影响。
服务与服务之间通讯采用 RPC 远程调用技术,但是每个服务中都有自己独立的数据源,即
自己独立的本地事务。两个服务相互通讯的时候,两个本地事务互不影响,从而出现分布式
事务产生的原因。

2 分布式事务概念名词

2.1 CAP(帽子原理)

1998 年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标。
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值,即写操作之后
的读操作,必须返回该值。(分为弱一致性、强一致性和最终一致性)
A:Availability,可用性,好的响应性能。完全的可用性指的是在任何故障模型下,服务都会在
有限的时间内处理完成并进行响应。
P: Partition tolerance,分区容忍性。尽管网络上有部分消息丢失,但系统仍然可继续工作。

2.2 主要矛盾-Consistency 和 Availability
CAP 理论就是说在分布式存储系统中,最多只能实现上面的两点。而由于网络硬件肯定会出
现延迟丢包等问题,所以分区容错性是我们必须需要实现的。所以我们只能在一致性和可用
性之间进行权衡,没有 NoSQL 系统能同时保证这三点。对于 web2.0 网站来说,关系数据库
的很多主要特性却往往无用武之地
数据库事务一致性需求 —— 很多 web 实时系统并不要求严格的数据库事务,对读一致性
的要求很低,有些场合对写一致性要求并不高。允许实现最终一致性。
数据库的写实时性和读实时性需求 ——对关系数据库来说,插入一条数据之后立刻查询,
是肯定可以读出来这条数据的,但是对于很多 web 应用来说,并不要求这么高的实时性,
比方说发一条消息之 后,过几秒乃至十几秒之后,我的订阅者才看到这条动态是完全可以
接受的。
对复杂的SQL 查询,特别是多表关联查询的需求 —— 任何大数据量的 web 系统,都非常
忌讳多个大表的关联查询,以及复杂的数据分析类型的报表查询,特别是 SNS 类型的网站,
从需求以及产品设计角 度,就避免了这种情况的产生。往往更多的只是单表的主键查询,
以及单表的简单条件分页查询,SQL 的功能被极大的弱化了。

2.3 BASE 理论
BASE 理论是指,Basically Available(基本可用)、Soft-state(软状态/柔性事务)、Eventual
Consistency(最终一致性)。是基于 CAP 定理演化而来,是对 CAP 中一致性和可用性权衡
的结果。核心思想:即使无法做到强一致性,但每个业务根据自身的特点,采用适当的方式
来使系统达到最终一致性。
1、基本可用:指分布式系统在出现故障的时候,允许损失部分可用性,保证核心可用。但
不等价于不可用。比如:搜索引擎 0.5 秒返回查询结果,但由于故障,2 秒响应查询结果;
网页访问过大时,部分用户提供降级服务,等。
2、软状态:软状态是指允许系统存在中间状态,并且该中间状态不会影响系统整体可用性。
即允许系统在不同节点间副本同步的时候存在延时。

3、最终一致性:
系统中的所有数据副本经过一定时间后,最终能够达到一致的状态,不需要实时保证系统数
据的强一致性。最终一致性是弱一致性的一种特殊情况。BASE 理论面向的是大型高可用可
扩展的分布式系统,通过牺牲强一致性来获得可用性。ACID 是传统数据库常用的概念设计,
追求强一致性模型。

2.4 柔性事务和刚性事务
柔性事务满足 BASE 理论(基本可用,最终一致)
刚性事务满足 ACID 理论

柔性事务分为
\1. 两阶段型
分布式事务二阶段提交,对应技术上的 XA、JTA/JTS,这是分布式环境下事务处理的典型模式。

\2. 补偿型
\3.
TCC 型事务(Try-Confirm-Cancel)可以归为补偿型。在 Try 成功的情况下,如果事务要回滚,Cancel 将作为一个补偿机制,回滚 Try 操作;TCC 各操作事务本地化,且尽早提交(没有两阶段约束);当全局事务要求回滚时,通过另一个本地事务实现“补偿”行为。
TCC 是将资源层的二阶段提交协议转换到业务层,成为业务模型中的一部分。

\3. 异步确保型
将一些有同步冲突的事务操作变为异步操作,避免对数据库事务的争用,如消息事务机制。

\4. 最大努力通知型几种。通过通知服务器(消息通知)进行,允许失败,有补充机制。
由于支付宝整个架构是 SOA 架构,因此传统单机环境下数据库
的 ACID 事务满足了分布式环境下的业务需要,以上几种事务类似就是针对分布式环境下业
务需要设定的。

2.5 分布式解决方案
①传统模式使用 Jta+Atomikos
②PC 与 3PC 实现的区别
③支付回调通知补偿型
④使用阿里巴巴 TCC 补偿框架
⑤使用可靠消息模式
⑥使用 LCN 框架解决分布式事务
⑦阿里 GTS 框架解决分布式事务

3 传统模式 Jta+Atomikos
传统项目中,比如项目中使用到多数据源的时候大多数采用 jta+Atomikos 解决分布式事务问
题,jta+Atomikos 底层是基于 XA 协议的两阶段提交方案。
XA 协议:XA 事务的基础是两阶段提交协议。需要有一个事务协调者来保证所有的事务参与
者都完成了准备工作(第一阶段)。如果协调者收到所有参与者都准备好的消息,就会通知所
有的事务都可以提交了(第二阶段)。Mysql 在这个 XA 事务中扮演的是参与者的角色,而
不是协调者(事务管理器)。
JTA:JTA(java Transaction API)是 JavaEE 13 个开发规范之一。java 事务 API,允许应用程序
执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JDBC 驱动程
序的JTA 支持极大地增强了数据访问能力。事务最简单最直接的目的就是保证数据的有效
性,数据的一致性
Atomikos:Atomikos TransactionsEssentials 是一个为Java平台提供增值服务的并且开源类事务
管理器

4 两阶段提交协议

第一阶段:
准备阶段:协调者向参与者发起指令,参与者评估自己的状态,如果参与者评估指令可以完
成,则会写 redo 或者 undo 日志,让后锁定资源,执行操作,但并不提交。
第二阶段:如果每个参与者明确返回准备成功,则协调者向参与者发送提交指令,参与者释
放锁定的资源,如何任何一个参与者明确返回准备失败,则协调者会发送中指指令,参与者
取消已经变更的事务,释放锁定的资源。
两阶段提交方案应用非常广泛,几乎所有商业 OLTP 数据库都支持 XA 协议。但是两阶段提
交方案锁定资源时间长,对性能影响很大,基本不适合解决微服务事务问题。
缺点:如果协调者宕机,参与者没有协调者指挥,则会一直阻塞。

5 三段提交协议

三阶段提交协议是两阶段提交协议的改进版本。它通过超时机制解决了阻塞的问题,并且把
1、引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
CanCommit阶段
3PC的CanCommit阶段其实和2PC的准备阶段很像。协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。
1.事务询问 协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
2.响应反馈 参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No
PreCommit阶段
协调者根据参与者的反应情况来决定是否可以记性事务的PreCommit操作。根据响应情况,有以下两种可能。
假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。
1.发送预提交请求 协调者向参与者发送PreCommit请求,并进入Prepared阶段。
2.事务预提交 参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
3.响应反馈 如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。
假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
1.发送中断请求 协调者向所有参与者发送abort请求。
2.中断事务 参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
doCommit阶段
该阶段进行真正的事务提交,也可以分为以下两种情况。
执行提交
1.发送提交请求 协调接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
2.事务提交 参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
3.响应反馈 事务提交完之后,向协调者发送Ack响应。
4.完成事务 协调者接收到所有参与者的ack响应之后,完成事务。
中断事务 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
1.发送中断请求 协调者向所有参与者发送abort请求
2.事务回滚 参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
3.反馈结果 参与者完成事务回滚之后,向协调者发送ACK消息
4.中断事务 协调者接收到参与者反馈的ACK消息之后,执行事务的中断。
在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者rebort请求时,会在等待超时之后,会继续进行事务的提交。(其实这个应该是基于概率来决定的,当进入第三阶段时,说明参与者在第二阶段已经收到了PreCommit请求,那么协调者产生PreCommit请求的前提条件是他在第二阶段开始之前,收到所有参与者的CanCommit响应都是Yes。(一旦参与者收到了PreCommit,意味他知道大家其实都同意修改了)所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到commit或者abort响应,但是他有理由相信:成功提交的几率很大。 )
2PC 与 3PC提交区别
增加了一个询问阶段,询问阶段可以确保尽可能早的发现无法执行操作而需要中止的行为,
但是它并不能发现所有的这种行为,只会减少这种情况的发生在准备阶段以后,协调者和参
与者执行的任务中都增加了超时,一旦超时,协调者和参与者都继续提交事务,默认为成功,
这也是根据概率统计上超时后默认成功的正确性最大
三阶段提交协议与两阶段提交协议相比,具有如上的优点,但是一旦发生超时,系统仍然会
发生不一致,只不过这种情况很少见罢了,好处就是至少不会阻塞和永远锁定资源。

6 Seata
6.1 介绍
http://seata.io/zh-cn/
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服
务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式
解决方案。
6.2,Seata 术语
1+3 的套件 1:全局唯一的事务 Id, XID
3 大组件

TC - 事务协调者(seata 服务器)
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM - 事务管理器(事务发起方)
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM - 资源管理器(事务参与方)
管理分支事务处理的资源,与 TC 交谈以注册分支事务和报告分支事务的状态,并驱动
分支事务提交或回滚。
4,处理过程
1),TM 向 TC 申请开启一个全局事务,全局事务创建成功,并生成一个全局唯一的 XID
2),XID 在微服务调用链路的上下文传播
3),RM 向 TC 注册分支事务,将其纳入 XID 对应的全局事务管辖
4),TM 向 TC 发起针对 XID 的全局提交或者回滚协议
5),TC 调度 XID 下的管辖的全部分支事务完成提交或者回滚的请求
5,执行流程
5.1 在第一阶段,seata会拦截业务SQL
l 解析SQL语义,找到业务SQL的更新业务数据,在业务数据被更新前,将其保存成“before Image”
l 执行业务SQL,更新业务数据
l 在业务数据更新之后,最后生成行锁

5.2 二阶段如果式顺利提交的话
应为业务SQL在第一阶段已经提交到数据库,所以Seata框架只需要将一阶段保存的快照数据和行锁删掉,完成数据清理即可

5.3 二阶段回滚
二阶段混滚的话,Seata就需要回滚一阶段已经执行的业务数据,还原业务数据
回滚的方式便是用before image的数据,但是还原前首先要校验脏写,对比数据库当前业务数据和after image,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就需要脏写,出现脏写需要人工处理

订单服务继承类,事务发起方,TM
@GlobalTransactional(name = “fsp-create-order”,rollbackFor = Exception.class)

UNDO_LOG 表
SEATA AT 模式需要 UNDO_LOG 表
– 注意此处0.3.0+ 增加唯一索引 ux_undo_logCREATE 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;

7 柔性事务的解决方案-----可靠消息最终一致(异步确保)

1)实现
• 业务处理服务在业务事务提交前,向实时消息服务请求发送消息,实时消息服务只记
录消息数据,而不真正发送。业务处理服务在业务事务提交后,向实时消息服务确认
发送。只有在得到确认发送指令后,实时消息服务才真正发送
2) 消息
• 业务处理服务在业务事务回滚后,向实时消息服务取消发送。消息状态确认系统定期
找到未确认发送或回滚发送的消息,向业务处理服务询问消息状态,业务处理服务根
据消息ID或消息内容确定该消息是否有效
3)约束
• 被动方的处理结果不影响主动方的处理结果, 被动方的消息处理操作是幂等操作
4)成本
• 可靠消息系统建设成本
• 一次消息发送需要两次请求,业务处理服务需实现消息状态回查接口
5) 优点、适用范围
• 消息数据独立存储、独立伸缩,降低业务系统与消息系统间的耦合
• 对最终一致性时间敏感度较高,降低业务被动方实现成本
6) 用到的服务模式
• 可查询操作、幂等操作
7) 方案特点
• 兼容所有实现JMS标准的MQ中间件(本教程中实现的方案)
• 确保业务数据可靠的前提下,实现业务数据的最终一致(理想状态下基本是准实时一致)
8)行业应用案例
• 支付宝、eBay(BASE)、去哪儿……

8 柔性事务解决方案----TCC(两阶段性,补偿性)

1) 实现
• 一个完整的业务活动由一个主业务服务与若干从业务服务组成
• 主业务服务负责发起并完成整个业务活动
• 从业务服务提供TCC型业务操作
• 业务活动管理器控制业务活动的一致性,它登记业务活动中的操作, 并在
业务活动提交时确认所有的TCC型操作的confirm操作,在业务活动取消
时调用所有TCC型操作的cancel操作
2) 成本
• 实现TCC操作的成本
• 业务活动结束时confirm或cancel操作的执行成本
• 业务活动日志成本
3) 适用范围
• 强隔离性、严格一致性要求的业务活动
• 适用于执行时间较短的业务(比如处理账户、收费等业务)
4)用到的服务模式
• TCC操作、幂等操作、可补偿操作、可查询操作
5) 方案特点
• 不与具体的服务框架耦合(在RPC架构中通用)
• 位于业务服务层,而非资源层
• 可以灵活选择业务资源的锁定粒度
• TCC里对每个服务资源操作的是本地事务,数据被lock的时间短,可扩展性好(可以说是为独立部署的SOA服务而设计的)
6)行业应用案例
• 支付宝XTS(蚂蚁金融云的分布式事务服务DTS)

9 柔性事务解决方案----最大努力通知性(非可靠消息,定期校对)

1)实现
•业务活动的主动方,在完成业务处理之后,向业务活动的被动方发送消息,允许消息丢失。
• 业务活动的被动方根据定时策略,向业务活动主动方查询,恢复丢失的业务消息。
2) 约束
• 被动方的处理结果不影响主动方的处理结果
3) 成本
• 业务查询与校对系统的建设成本
4) 适用范围
• 对业务最终一致性的时间敏感度低
• 跨企业的业务活动
5)用到的服务模式
• 可查询操作
6)方案特点
• 业务活动的主动方在完成业务处理后,向业务活动被动方发送通知消息(允许消息丢失)
• 主动方可以设置时间阶梯型通知规则,在通知失败后按规则重复通知,直到通知N次后不再通知
• 主动方提供校对查询接口给被动方按需校对查询,用于恢复丢失的业务消息
7)行业应用案例
• 银行通知、商户通知等(各大交易业务平台间的商户通知:多次通知、查询校对、对账文件)

10 柔性事务-LCN框架解决分布式事务

1)介绍
LCN不生产事务,只是本地事务的搬运工
兼容 dubbo、springcloud、motan 框架,支持各种关系型数据库
2)功能特点
无侵入式支持分布式事务。
支持多种模式混合使用。
支持关系型数据、NoSQL数据库。
支持SpringCloud Dubbo等RPC框架。
支持负载均衡与集群化部署。
高性能与高稳定性。
3)实现原理
1.LCN客户端(发起方和参与方都必须要注册到事务协调者中) 建立一个长连接。
2.订单服务(发起方)调用库存服务接口(参与方)之前会向TxManager事务协调者创建一个事务的分组id。
3.订单服务(发起方)调用库存服务接口(参与方)的时候,会在请求头中存放该事务的分组id,给库存服务。
4.如果库存服务获取到请求头中有对应的事务分组id,库存服务业务逻辑代码执行完毕的,会采用假关闭,不会提交该事务。
5.参与方在什么时候提交事务。
答案:肯定在发起方 执行成功下。
订单服务(发起方)调用库存服务接口(参与方)之后,如果订单服务(发起方)执行没有问题的下,
订单服务(发起方)使用对应的事务分组id,通知给TxManager事务协调者,让后TxManager事务协调者在根据该事务分组id,通知给所有的参与方提交事务。
解答:长连接 好处减少宽带传输 弊端比较占内存。
6核心步骤
创建事务组
是指在事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。
添加事务组
添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息添加通知给TxManager的操作。
关闭事务组
是指在发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager的动作。当执行完关闭事务组的方法以后,TxManager将根据事务组信息来通知相应的参与模块提交或回滚事务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大道至简@EveryDay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值