分布式事务及二阶段提交与TCC

什么是分布式事务

分布式事务就是在分布式系统中运行的事务,它是由多个本地事务组成的。也需要满足事务的ACID特性。关于ACID见我的博文《事务的ACID特性与隔离性分析》

二阶段提交

二阶段提交协议(The two-phase commit protocol, 2PC),是用于保证分布式事务的原子性与一致性,其分为投票(vote)与提交(commit)2个阶段。为了实现二阶段提交,需要引入协调者(coordinator,即事务的管理器),来保证事务的原子性与一致性。
1、投票(vote)为第一阶段,协调者(coordinator,即事务的管理器)向事务的所有参与者(即本地资源管理器)发起执行操作的canCommit请求,并等待参与者的放回值。参与者收到请求后,会执行请求中的事务操作,并记录日志,但不提交。如果所有的操作都执行成功,则返回yes,否则返回no。
2、提交(commit)为第二阶段,协调者收到所有的事务参与者的回复后:如果所有参与者都回复yes,则协调者向所有参与者发送doCommit请求,参与者收到doCommit请求后执行commit提交事务,提交完成后回复haveCommited请求;
3、如果某个参与者回复no,则协调者向所有参与者发送doAbort请求,参与者收到doAbort请求后执行rollback回滚事务,回滚完成后回复haveCommited请求。协调者收到haveCommited请求后,分布式事务就结束了。

二阶段提交问题

1、单点故障问题,事务管理器存在单点故障问题,如果事务管理器发生故障,那么整个系统将不可用。特别是如果事务的部分参与者处于投票阶段,如果事务管理器发生故障,那么资源管理器的资源将得不到释放,从而导致资源长时间堵塞;
2、数据不一致问题,在事务的提交阶段,如果事务管理器发生故障或者部分参与者的网络出现异常,那么部分参与者可能提交了事务,但是其他一些参与者没有提交事务,数据处于不一致状态;
3、同步堵塞问题,事务的参与者在收到第一阶段的canCommit请求后,就执行了事务的操作且记录日志,那么就会锁住事务涉及的资源,直到协调者提交事务。整个系统存在严重的并发冲突,从而影响系统的吞吐量;
4、引入了协调者,请求的处理多了一跳,影响响应时间,为此一般协调者与业务代码放到一块。

基于XA协议的二阶段提交算法例子

我们一般使用基于XA协议的二阶段提交算法,我们以一个银行转账为例子,假如需要小王要从自己的A银行转账100元到小李的B银行,假设A银行与B银行都有一个账户资产表asset,其表结构如下:

CREATE TABLE asset
(`acct` VARCHAR(64) NOT NULL,
`asset` BIGINT(32) NOT NULL,
PRIMERY KEY `acct`);

那么XA协议的二阶段提交算法是这样执行的:
1、A银行与B银行向数据库分别发起如下的操作,准备执行的SQL语句:

XA START ‘xid’;
UPDATE asset SET asset=asset-100 WHERE acct=’小王’ AND asset >=100;
XA END ‘xid’;
XA START ‘xid’;
UPDATE asset SET asset=asset+100 WHERE acct=’小李’;
XA END ‘xid’;

2、A银行发起二阶段提交的canCommit请求,A银行与B银行都向数据库发起如下的语句,锁住资源

XA PREPARE ‘xid’;

3、A银行根据A银行与B银行的返回值,发起doCommit或者doAbort请求,A银行与B银行执行如下的语句

XA COMMIT ‘xid’;或者XA ROLLBACK ‘xid’;

需要注意得是,上面流程中xid必须是唯一的。

什么是TCC?

TCC是Try、Confirm与Cancel三个单词首字母得缩写,它定义了3个操作:预留(Try)、确认(Confirm)与撤销(Cancel)。
1、预留(Try),类似于二阶段提交中的canCommit阶段(第一阶段),具体来说就是,系统需要将事件需要的资源预留且锁定;
2、确认(Confirm),类似于二阶段提交中的confirm提交事务,如果所有的资源都预留锁定成功,那么调用确认操作,系统确认事件;
3、撤销(Cancel),类似于二阶段提交中的rollback回滚事务,如果某个资源预留锁定失败,那么调用撤销操作,系统将撤销之前预留且锁定的资源,从而恢复到try操作之前的状态。
对于预留(Try)、确认(Confirm)与撤销(Cancel)三个操作如果网络异常或者超时需要重试,为此这3个操作需要支持幂等。

TCC例子

还是以前面银行转账为例子,那么表结构需要添加冻结字段,需要改成:

CREATE TABLE asset
(
`acct` VARCHAR(64) NOT NULL,
`asset` BIGINT(32) NOT NULL,
`hold` BIGINT(32) NOT NULL,
PRIMERY KEY `acct`
);

那么TCC的执行流程是这样的:
1、预留(Try)操作:对于A银行,需检查小王的账户的合法性且资产-冻结是否大于等于100元,如果都满足执行如下的操作:

UPDATE asset SET hold=hold+100 WHERE acct=’小王’ AND asset-hold >=100;

冻结100元且回复yes,否则返回no;对于B银行,需检查小李的账户的合法性,如果合法返回yes,否则返回no
2、如果A银行与B银行都返回yes,则执行确认(Confirm)操作:对于A银行,生效之前的冻结其SQL语句如下:

UPDATE asset SET asset=asset-100,hold=hold-100 WHERE acct=’小王’;

对于B银行,在小李的账户增加100元,其SQL语句如下:

UPDATE asset SET asset=asset+100 WHERE acct=’小李’;

3、如果A银行与B银行其中一个返回no,则执行撤销(Cancel)操作:对于A银行,撤销之前冻结的金额,其SQL语句如下:

UPDATE asset SET hold=hold-100 WHERE acct=’小王’

对于B银行,由于try操作只是检查了账户的合法性,所以不需要做任何操作。
从上面的实例中可以看出,TCC对于业务逻辑是有侵入性的,但是由于它不需要锁定资源,故性能会更好,并且其也可以实现分布式事务的原子性与一致性。

TCC与XA规范的二阶段提交对比

1、TCC是一个业务层面的分布式事务协议;而XA是数据层面的分布式协议;
2、TCC对业务逻辑有侵入性,需要根据业务场景设计预留(Try)、确认(Confirm)与撤销(Cancel)操作;而XA对业务逻辑没有侵入性;
3、TCC的三个操作,每个都是本地事务,操作完成事务就结束了,不会长时间锁住资源,性能更高;而XA在第一阶段就会锁定资源,直到第二阶段的提交或者回滚操作,资源锁定时间较长,严重影响性能;
4、TCC是一种业务上的规范,所有的场景都适用;
5、TCC实现上更复杂,没有单点故障与数据不一致问题;而XA有这2个问题;
6、与XA协议一样,也需要一个协调者来管理事务。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值