前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >分布式事务的实现思想

分布式事务的实现思想

作者头像
剑影啸清寒
发布2020-07-13 10:26:49
5100
发布2020-07-13 10:26:49
举报
文章被收录于专栏:琦小虾的Binary琦小虾的Binary

分布式事务的实现思想

参考地址:《从银行转账失败到分布式事务:总结与思考》

分布式事务的基本概念与本地事务类似,都保证了 ACID 特性(见本篇第二章)。随着数据的规模越来越大,就出现了对业务的解构,包括数据层面的关系型数据库的垂直、水平分表,以及服务层面的拆分,将一个大服务拆分为后单独部署,甚至同时也将数据库独立出来。这时候本地数据库事务就不能满足多个数据库、异构系统的原子性、持久性了,需要使用分布式事务的方法。通常,分布式事务只需要保证原子性,通过保证原子性来保证应用层面的一致性,由本地事务保证隔离性和持久性。

从 CAP 特性上考虑,由于分布式事务存在网络分割的情况,所以一定需要满足分区容忍性,剩下的需要在一致性 (Consistency)可用性 (Available) 之间做权衡。下面提到各种分布式事务的实现方法与协议,都是需要在一致性与可用性之间权衡的。

1. 二阶段提交协议 (2PC)

二阶段提交 (Two-phase Commit Protocol) 是非常经典的强一致性、中心化的原子提交协议,协议中有两类节点:一个中心化协调者 (Coordinator) 节点N 个参与者 (Cohort) 节点

2PC 每一次事务提交都分为两个阶段:

  1. 协调者询问所有的参与者是否可以提交事务,所有参与者向协调者投票;
  2. 协调者根据参与者的投票结果,做出是否事务可以全局提交的决定,并通知所有参与者执行该决定。

2PC 提交流程中,参与者不能改变自己的投票结果。此外,2PC 可以全局提交的前提,是所有参与者都同意提交事务。只要有一个参与者投票,选择放弃事务,则全局事务必须被放弃。

2PC 的优缺点:

  • 优点:
    • 强一致性。只要节点或者网络最终恢复正常,协议就能保证顺利结束;
    • 部分关系型数据库(如 Oracle)、框架直接支持;
  • 缺点:
    • 容错能力较差:比如节点宕机、超时的情况下,无法确定流程的状态,只能不断重试;
    • 性能较差,交互消息多,受最慢节点影响。
    • 访问共享资源你的时候,发生冲突和死锁的概率增高。随着数据库节点增多,这种趋势越来越严重。

2. 三阶段提交协议 (3PC)

相较于两阶段提交协议,三阶段提交协议 (3PC) 解决了阻塞问题,将两个阶段扩展为三个阶段,增加了超时机制。虽然解决了 2PC 情况下的阻塞问题,但一次提交要传递六次消息,延时很大。

3. TCC

TCC 是 Try, Commit, Cancel 的缩写,保证强一致性的同时,最大限度提高系统的可伸缩性与可用性

假设一个完整的业务包含一组子业务:

  • Try:完成所有子业务检查,预留必要的业务资源,实现与其他事务的隔离;
  • Confirm:使用 Try 阶段预留的业务资源,真正执行业务;同时满足幂等性,支持重试;
  • Cancel:释放 Try 资源预留的业务资源,同样满足幂等性。

一次完整的交易,由一系列微交易的 Try 操作组成,如果所有 Try 操作都成功,最后由微交易框架统一 Confirm,否则统一 Cancel,这样实现了类似 2PC 的强一致性。TCC 的特点有:

  • Try 操作兼具资源操作与准备能力,没有单独的准备阶段 (Prepare),这样降低了提交协议的成本;
  • Try 操作由业务层保证原子性,这样也可以灵活选择业务资源的锁定粒度,而不是锁住整个资源,提高了整体的并发度;
  • TCC 的所有子业务都要事先自己的 Confirm, Cancel 操作,实现相应的补偿逻辑,所以需要较高的开发成本。

4. 基于消息的分布式事务

基于异步消息的事务机制,可以分为主事务从事务两部分。主事务本地先行提交,然后通过消息通知各个从事务,从事务收到主事务发来的消息后,各自进行本地提交。

由上面可以得知,这是一种异步事务机制,虽然只保证最终一致性,但可用性非常高,不会因为故障发生阻塞。

实现异步消息的事务机制有本地消息表事务消息两种方式,两种方式都可以保证主事务的提交与消息发送两者之间的原子性。下面以转账操作为例,转账操作分为四步:用户 A 扣钱,发送消息,用户 B 接受消息,用户 B 扣钱。其中前两步肯定是原子性的,本地消息表和事务消息的解决方案分别如下:

4.1 本地消息表

本地消息表的含义如字面意思,将消息存到本地数据库中,通过本地事务保证消息的存入。依旧是上面的转账例子,伪代码如下:

begin transaction:
	update user set account = account - 100 where userId = '00000000';
	insert into message(userId, amount, status) values ('00000000', 100, 1);
commit transaction

主事务通过这种本地数据库事务的方式,保证数据库中扣除 A 的操作,和向数据库中存入消息(类似于消费流水信息)的操作是原子性的。然后从事务定时的从数据库中拉取消息,然后执行。

4.2 事务消息

事务消息的部分见《Kafka 篇》第二章事务部分

将事务消息与本地消息表对比,事务消息不依赖于本地数据库存储消息,而是通过消息中间件保证本地事务与消息的原子性。但是实现了事务的消息队列比较少,不能通用化使用。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分布式事务的实现思想
    • 1. 二阶段提交协议 (2PC)
      • 2. 三阶段提交协议 (3PC)
        • 3. TCC
          • 4. 基于消息的分布式事务
            • 4.1 本地消息表
            • 4.2 事务消息
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档