浅谈「事务 & 分布式事务」

事务

什么是事务?

事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。

MySQL 支持事务吗?

答案

在缺省模式下,MYSQL 是 autocommit 模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql 是不支持事务的。

但是如果你的 MYSQL 表类型是使用 InnoDB Tables 或 BDB tables 的话,你的 MYSQL 就可以使用事务处理

  • 使用 SET AUTOCOMMIT = 0 就可以使 MYSQL 开启非autocommit 模式
  • 非 autocommit 模式下,你必须使用 COMMIT 来提交你的更改,且用 ROLLBACK 来回滚你的更改
  • 示例如下:
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

分布式事务

平时所见的事务是单机下的事务,这里介绍一下分布式事务。

没有分布式事务的系统会出现什么问题?

在讲解分布式事务之前先来说一下如果没有分布式事务会如何?

在一系列微服务系统当中,假如不存在分布式事务,会发生什么呢?让我们以互联网中常用的交易业务为例:

上图中包含了库存和订单两个独立的微服务,每个微服务维护了自己的数据库。在交易系统的业务逻辑中,一个商品在下单之前需要先调用库存服务,进行扣除库存,再调用订单服务,创建订单记录。

正常情况下,两个数据库各自更新成功,两边数据维持着一致性。

但是,在非正常情况下,有可能库存的扣减完成了,随后的订单记录却因为某些原因插入失败。这个时候,两边数据就失去了应有的一致性。

这种时候必须要保证数据的一致性,单数据源的一致性依靠单机事务来保证,多数据源的一致性就要依靠分布式事务

什么是分布式事务?

分布式事务用于在分布式系统中保证不同节点之间的数据一致性。分布式事务的实现有很多种,最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议

XA协议有两阶段提交(2PC)三阶段提交(3PC)两种实现,这里我们重点介绍两阶段提交的具体过程。

两阶段提交

XA 协议的运作方式,和魔兽世界中的团队协作有些类似,在魔兽世界这款游戏中,副本组团打BOSS的时候,为了更方便队长与队员们之间的协作,队长可以发起一个“就位确认”的操作:当队员收到就位确认提示后,如果已经就位,就选择“是”,如果还没就位,就选择“否”。当队长收到了所有人的就位确认,就会向所有队员们发布消息,告诉他们开始打BOSS。

这个流程和XA分布式事务协议的两阶段提交非常相似。

那么XA协议究竟是什么样子呢?在XA协议中包含着两个角色:事务协调者事务参与者。来看一看它们之间的交互流程:

第一阶段

在XA分布式事务的第一阶段,作为事务协调者的节点会首先向所有的参与者节点发送Prepare请求。

在接到Prepare请求之后,每一个参与者节点会各自执行与事务有关的数据更新,写入Undo LogRedo Log。如果参与者执行成功,则暂时不提交事务,而是向事务协调节点返回“完成”消息。

当事务协调者接到了所有参与者的返回消息,整个分布式事务将会进入第二阶段。
第二阶段

在XA分布式事务的第二阶段,如果事务协调节点在之前所收到都是正向返回,那么它将会向所有事务参与者发出Commit请求。

接到Commit请求之后,事务参与者节点会各自进行本地的事务提交,并释放锁资源。当本地事务完成提交后,将会向事务协调者返回“完成”消息。

当事务协调者接收到所有事务参与者的“完成”反馈,整个分布式事务完成。

以上所描述的是XA两阶段提交的正向流程,接下来我们看一看失败情况的处理流程

第一阶段

第二阶段

在XA的第一阶段,如果某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。

于是在第二阶段,事务协调节点向所有的事务参与者发送Abort请求。接收到Abort请求之后,各个事务参与者节点需要在本地进行事务的回滚操作,回滚操作依照Undo Log来进行。

以上就是XA两阶段提交协议的详细过程。

XA两阶段提交协议的不足

XA两阶段提交协议虽然解决了分布式事务的一致性问题,但仍然存在着许多不足之处:

  1. 性能问题

XA协议遵循强一致性。在事务执行过程中,各个节点占用着数据库资源,只有当所有节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。这样的过程有着非常明显的性能问题。

  1. 协调者单点故障问题

事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态无法完成事务。

  1. 丢失消息导致的不一致问题

在XA协议的第二个阶段,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。

解决方案

如果避免XA两阶段提交的种种问题呢?有许多其他的分布式事务方案可供选择:

  1. XA三阶段提交

XA三阶段提交在两阶段提交的基础上增加了CanCommit 阶段,并且引入了超时机制。一旦事物参与者迟迟没有接到协调者的 commit 请求,会自动进行本地 commit。这样有效解决了协调者单点故障的问题。但是性能问题和不一致的问题仍然没有根本解决。

  1. MQ事务

利用消息中间件异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像XA协议那样的性能问题。

  1. TCC事务

TCC事务是Try、Commit、Cancel三种指令的缩写,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面来人为实现。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值