蚂蚁金服分布式事务开源以及实践 | SOFA 开源一周年献礼

简介: 上周,分布式事务 Fescar 宣布进行品牌升级为 Seata,蚂蚁金服在 Seata 0.4.0 版本加入了 TCC 模式,后续也会持续输入。本文根据 SOFAMeetup 北京站现场分享整理详细,讲述了分布式事务在蚂蚁金服的发展以及开源版本的规划,希望可以帮助大家理解。

上周,分布式事务 Fescar 宣布进行品牌升级:

Thanks, Fescar ️,
Hello, Seata 。

Seata 意为:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事务解决方案。
项目地址:https://github.com/seata/seata

image.png

蚂蚁金服在 Seata 0.4.0 版本加入了 TCC 模式,后续也会持续输入。

为了帮助大家理解,分布式事务开源负责人绍辉进行了一次线下分享,详细讲述了分布式事务在蚂蚁金服的发展,希望可以帮助大家理解分布式事务,以下为分享的文字整理版本。

前言

今天的分享将从以下三个部分展开:分布式事务问题产生的背景、蚂蚁金服分布式事务以及分布式事务 Seata 的 Roadmap。

image.png
分享嘉宾:绍辉 蚂蚁金服 分布式事务开源负责人

1、分布式事务问题产生的背景

1.1、数据库的水平拆分

蚂蚁金服早期,业务量比较小,单库单表便能满足业务需求;但是随着业务的发展,单库单表数据库逐渐成为瓶颈。为了解决数据库的瓶颈问题,我们对数据库进行了水平拆分。拆分所带来的一个问题就是以前一个数据库上便能完成的写操作现在要跨多个数据库,由此带来了跨库事务问题。

image.png

1.2、业务的服务化拆分

蚂蚁金服早期是单系统架构,所有业务服务几乎都在少数几个 APP 中。随着业务的发展,业务越来越复杂,服务之间的耦合度也越来越高,故我们对系统进行了重构,服务按照功能进行解耦和垂直拆分。拆分之后所带来的问题就是一个业务活动原来只需要调用一个服务就能完成,现在需要调用多个服务才能完成,由此产生了跨服务事务问题。

image.png

1.3、转账案例说明数据一致性问题

数据库的水分拆分以及服务的垂直拆分,所带来的问题是一个业务活动通常要调用多个服务、访问多个数据库才能完成。

以金融业务场景下的转账场景为例,转账服务要完成以下操作:

  1. 调用交易系统服务创建交易订单;
  2. 调用支付系统记录支付明细;
  3. 调用账务系统执行 A 扣钱;
  4. 调用账务系统执行 B 加钱。

以上 4 个操作要跨 3 个系统,访问 4 个数据库。而网络、数据库、机器等都具有不可靠性,我们很难保证以上 4 个操作能 100% 全部成功。

在金融属性的业务中,不允许 A 账户的钱扣了,而 B 账户的钱没有加上的现象出现,所以我们必须想办法保证 1 ~ 4 这四个操作要么全部成功,要么全部失败;所以蚂蚁金服自主研发了分布式事务中间件,解决跨服务、跨数据库的数据一致性问题。

image.png

2、蚂蚁金服分布式事务

2.1、分布式事务理论基础

在介绍蚂蚁金服的分布式事务中间件之前,先介绍一些分布式事务的理论背景。

  • 2PC

两阶段提交协议(Two Phase Commitment Protocol)是分布式事务最基本的协议。在两阶段提交协议中,有一个事务管理器和多个资源管理器,事务管理器分两阶段协调资源管理器。在第一阶段,事务管理器询问所有资源管理器准备是否成功。如果所有资源均准备成功,那么在第二阶段事务管理器会要求所有资源管理器执行提交操作;如果任一资源管理器在第一阶段返回准备失败,那么事务管理器会要求所有资源管理器在第二阶段执行回滚操作。通过事务管理器的两阶段协调,最终所有资源管理器要么全部提交,要么全部回滚,最终状态都是一致的。

image.png

  • TCC

资源管理器有很多实现方式,其中 TCC(Try-Confirm-Cancel)是资源管理器的一种服务化的实现。TCC 是一种比较成熟的分布式事务解决方案,可用于解决跨数据库、跨服务业务操作的数据一致性问题。TCC 其 Try、Confirm、Cancel 3 个方法均由业务编码实现,故 TCC 可以被称为是服务化的资源管理器。

TCC 的 Try 操作作为一阶段,负责资源的检查和预留;Confirm 操作作为二阶段提交操作,执行真正的业务;Cancel 是二阶段回滚操作,执行预留资源的取消,使资源回到初始状态。

如下图所示,用户实现 TCC 服务之后,该 TCC 服务将作为分布式事务的其中一个资源,参与到整个分布式事务中。事务管理器分两个阶段协调 TCC 服务,在第一阶段调用所有 TCC 服务的 Try 方法,在第二阶段执行所有 TCC 服务的 Confirm 或者 Cancel 方法,最终所有 TCC 服务要么全部都是提交的、要么全部都是回滚的。

image.png

2.2、蚂蚁金服分布式产品介绍

蚂蚁金服从 2007 年开始做分布式事务,至今已经有 12 年历史。蚂蚁金服的分布式事务最初是采用 TCC 实现的,TCC 模式帮蚂蚁业务解决了各类金融核心场景下的数据一致性问题。

2007 年我们开始支持双十一,为了满足双十一的高性能需求,我们对分布式事务做了一系列的性能优化。

2013年,蚂蚁金服开始做单元化改造,分布式事务也开始支持 LDC、异地多活和高可用容灾,解决了机房故障情况下服务快速恢复的问题。

2014年,蚂蚁金服分布式事务中间件开始通过蚂蚁金融云对外输出,我们发展了一大批的外部用户;在发展外部客户的过程中,外部客户表示愿意牺牲一部分性能(无蚂蚁的业务规模)以换取接入便利性和无侵入性。

所以在 2015年,我们开始做无侵入的事务解决方案:FMT 模式和 XA 模式。

image.png

蚂蚁金服分布式事务中间件经过长期演进,目前积累了 TCC、FMT 和 XA 三种模式,具有丰富的应用场景。下面分别介绍这三种模式。

2.3、TCC 模式

蚂蚁金服的 TCC 模式和前面介绍 TCC 理论中提的 TCC 原理是一致的。不同的是,我们在整个分布式事务执行过程中,会去记录事务日志,一个分布式事务会产生一条主事务记录(对应发起方)和若干分支事务记录(对应 TCC 参与者)。记录事务日志的目的是,当分布式事务执行过程中出现异常中断时,事务恢复服务通过轮询事务日志,找出这个异常中断的事务,补偿执行该异常事务剩余未完成的动作,整个分布式事务的最终状态要么全部提交,要么全部回滚。

image.png

TCC 设计规范和注意事项:

用户在接入 TCC 时,大部分工作都集中在如何实现 TCC 服务上。经过蚂蚁金服多年的 TCC 应用实践,总结如下在 TCC 设计和实现过程中的注意事项:

1、业务操作分两阶段完成:

接入 TCC 前,业务操作只需要一步就能完成。但是在接入 TCC 之后,需要考虑如何将其分成两个阶段完成:把资源的检查和预留放在一阶段的 Try 操作中进行,把真正的业务操作的执行放在二阶段的 Confirm 操作中进行。

以下举例说明业务模式如何分成两阶段进行设计,举例场景:“账户 A 的余额中有 100 元,需要扣除其中 30 元”。

在接入 TCC 之前,用户编写 SQL:“update 账户表 set 余额 = 余额 -20 where 账户 = A”,便能一步完成扣款操作。

在接入 TCC 之后,就需要考虑如何将扣款操作分成两步完成:

  • Try 操作:资源的检查和预留。

在扣款场景,Try 操作要做的事情就是先检查 A 账户余额是否足够,再冻结要扣款的 30 元(预留资源);此阶段不会发生真正的扣款。

  • Confirm 操作:执行真正业务的提交。

在扣款场景下,Confirm 阶段做的事情就是发生真正的扣款,把 A 账户中已经冻结的 30 元钱扣掉。

  • Cancel 操作:预留资源的释放。

在扣款场景下,扣款取消,Cancel 操作执行的任务是释放 Try 操作冻结的 30 元钱,使 A 账户回到初始状态。

image.png

2、并发控制

用户在实现 TCC 时,应当考虑并发性问题,将锁的粒度降到最低,以最大限度提高分布式事务的并发性。

以下还是以 A 账户扣款为例,“账户 A 上有 100 元,事务 T1 要扣除其中的 30 元,事务 T2 也要扣除 30 元,出现并发”。

在一阶段 Try 操作中,分布式事务 T1 和分布式事务 T2 分别冻结资金的那一部分资金,相互之间无干扰。这样在分布式事务的二阶段,无论 T1 是提交还是回滚,都不会对 T2 产生影响,这样 T1 和 T2 可以在同一笔业务数据上并行执行。

image.png

3、允许空回滚

如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因为丢包而导致的网络超时。此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,而 Cancel 操作调用未出现超时。

TCC 服务在未收到 Try 请求的情况下收到 Cancel 请求,这种场景被称为空回滚。空回滚在生产环境经常出现,用户在实现 TCC 服务时,应允许空回滚的执行,即收到空回滚时返回成功。

image.png

4、防悬挂控制

如下图所示,事务协调器在调用 TCC 服务的一阶段 Try 操作时,可能会出现因网络拥堵而导致的超时。此时事务管理器会触发二阶段回滚,调用 TCC 服务的 Cancel 操作,Cancel 调用未超时。在此之后,拥堵在网络上的一阶段 Try 数据包被 TCC 服务收到,出现二阶段 Cancel 请求比一阶段 Try 请求先执行的情况,此 TCC 服务在执行晚到的  Try 之后,将永远不会再收到二阶段的 Confirm 或者 Cancel,造成 TCC 服务悬挂。

用户在实现 TCC 服务时,要允许空回滚,但是要拒绝执行空回滚之后 Try 请求,要避免出现悬挂;

image.png

5、幂等控制

无论是网络数据包重传,还是异常事务的补偿执行,都会导致 TCC 服务的 Try、Confirm 或者 Cancel 操作被重复执行;用户在实现 TCC 服务时,需要考虑幂等控制,即 Try、Confirm、Cancel 执行一次和执行多次的业务结果是一样的。

image.png

2.4、FMT 模式

FMT(Framework-managed transaction)框架管理事务,是一种无侵入的事务解决方案。该模式下,分布式事务框架会托管所有的事务操作,事务的一阶段和二阶段操作均由框架自动生成,用户 SQL 将作为分布式事务的一阶段,而二阶段由框架自动生成“提交/回滚”操作。

image.png

1、FMT 一阶段

FMT 的一阶段是分布式事务框架自动生成的,分布式事务框架会在一阶段拦截业务的 SQL 语句,在业务执行前,将业务 SQL 修改前的数据保存成原快照(undo log);在业务 SQL 执行之后,将更新的业务数据保存成新快照(redo log),最后用表名+主键值的方式生成行锁,来做分布式事务的并发控制。

解析 SQL 语义的目的是为了便于找到业务要更新的业务数据;而提取表元数据的目的为了找到业务表的主键和唯一性约束键,便于生成行锁。

image.png

2、FMT 二阶段

FMT 模式下,一阶段主要是为了保持 undo log、redo log 等中间数据,保持这些中间数据的目的是为了生成二阶段的操作。

image.png

  • FTM 二阶段提交

二阶段提交操作是自动生成的,由于业务 SQL 在一阶段已经提交至数据库,故二阶段提交只需删除一阶段保存的中间数据(undo  log、redo log和行锁)。

  • FMT 二阶段回滚

二阶段回滚操作也是自动生成的,目的是使用 undo log 回滚一阶段业务 SQL 更新的业务数据。具体操作步骤是:

首先,需要校验脏写。校验脏写的方式使用 redo log 与数据库当前值进行对比,如果两份数据完全一致则说明没有出现脏写,如果两份数据不一致,则说明出现脏写;如果出现脏写,就需要转人工处理,不能再使用 undo log 回滚业务数据。

然后,还原业务数据。如果未出现脏写,则使用 undo log 回滚业务数据,使业务数据恢复到初始的值。

最后,删除中间数据。业务数据还原之后,便可以将中间数据(undo  log、redo log和行锁)全部删掉,完成回滚操作。

2.5、XA 模式

XA 模式是另外一种无侵入的分布式事务解决方案,不同于 FMT 的是,XA 模式下,所有一阶段和二阶段都由数据库来完成。蚂蚁分布式事务框架在一阶段调用数据的一阶段 XA 接口(xa prepare),在二阶段调用数据的二阶段 XA 接口(xa commit/xa rollback)。

image.png

XA 模式有以下特点:

  1. 主流的数据库均支持 XA 写,覆盖面广;
  2. 与蚂蚁自研数据库 Oceanbase 深度定制,解决 XA 事务性能问题;
  3. 借助数据库的 MVCC 特性,实现了分布式 MVCC 和全局一致性读。

3、蚂蚁金服投入分布式事务 Seata 社区共建

2019 年 1 月,基于技术积累,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & EaSy Commit And Rollback, Fescar),和社区一起共建分布式事务解决方案。Fescar 为解决微服务架构下的分布式事务问题交出了一份与众不同的答卷。而 Fescar 的愿景是让分布式事务的使用像本地事务的使用一样简单和高效。最终的目标是希望可以让 Fescar 适用于所有的分布式事务场景。

为了达到适用于更多的分布式事务业务场景的目标,蚂蚁金服加入 Fescar 社区共建,加入了 TCC 模式。

蚂蚁金服的加入引发了社区核心成员的讨论,为了达到适用于所有的分布式事务业务场景的目标,也为了社区更中立、更开放、生态更加丰富,社区核心成员们决定进行品牌升级,改名 Seata。Seata 意为:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事务解决方案。

自开源以来,Seata 一直受益于社区的贡献。截止目前,分布式事务 Seata 已经拥有超过 7000 的 Star ,超 55 位 Contributors,开发者们的加入,使得社区的生态更加丰富也更有活力。

2019 年 5 月,Seata 将加入服务端 HA 集群支持,从此,Seata 可以达到生产环境使用的标准。

欢迎对分布式事务有热情的开发者们加入社区的共建中来,为 Seata 带来更多的想象空间。

分布式事务.png

总结

目录
相关文章
|
2月前
|
运维 Kubernetes 调度
阿里云容器服务 ACK One 分布式云容器企业落地实践
3年前的云栖大会,我们发布分布式云容器平台ACK One,随着3年的发展,很高兴看到ACK One在混合云,分布式云领域帮助到越来越多的客户,今天给大家汇报下ACK One 3年来的发展演进,以及如何帮助客户解决分布式领域多云多集群管理的挑战。
阿里云容器服务 ACK One 分布式云容器企业落地实践
|
3月前
|
存储 分布式计算 Hadoop
【揭秘Hadoop背后的秘密!】HDFS读写流程大曝光:从理论到实践,带你深入了解Hadoop分布式文件系统!
【8月更文挑战第24天】Hadoop分布式文件系统(HDFS)是Hadoop生态系统的关键组件,专为大规模数据集提供高效率存储及访问。本文深入解析HDFS数据读写流程并附带示例代码。HDFS采用NameNode和DataNode架构,前者负责元数据管理,后者承担数据块存储任务。文章通过Java示例演示了如何利用Hadoop API实现数据的写入与读取,有助于理解HDFS的工作原理及其在大数据处理中的应用价值。
77 1
|
3月前
|
机器学习/深度学习 人工智能 负载均衡
【AI大模型】分布式训练:深入探索与实践优化
在人工智能的浩瀚宇宙中,AI大模型以其惊人的性能和广泛的应用前景,正引领着技术创新的浪潮。然而,随着模型参数的指数级增长,传统的单机训练方式已难以满足需求。分布式训练作为应对这一挑战的关键技术,正逐渐成为AI研发中的标配。
187 5
|
3月前
|
存储 Kubernetes 监控
深入浅出分布式事务:理论与实践
在数字化时代的浪潮中,分布式系统如同星辰大海般浩瀚而深邃。本文将带你航行于这片星辰大海,探索分布式事务的奥秘。我们将从事务的基本概念出发,逐步深入到分布式事务的核心机制,最后通过一个实战案例,让你亲自体验分布式事务的魅力。让我们一起揭开分布式事务的神秘面纱,领略其背后的科学与艺术。
79 1
|
3月前
|
UED 存储 数据管理
深度解析 Uno Platform 离线状态处理技巧:从网络检测到本地存储同步,全方位提升跨平台应用在无网环境下的用户体验与数据管理策略
【8月更文挑战第31天】处理离线状态下的用户体验是现代应用开发的关键。本文通过在线笔记应用案例,介绍如何使用 Uno Platform 优雅地应对离线状态。首先,利用 `NetworkInformation` 类检测网络状态;其次,使用 SQLite 实现离线存储;然后,在网络恢复时同步数据;最后,通过 UI 反馈提升用户体验。
76 0
|
3月前
|
机器学习/深度学习 TensorFlow 数据处理
分布式训练在TensorFlow中的全面应用指南:掌握多机多卡配置与实践技巧,让大规模数据集训练变得轻而易举,大幅提升模型训练效率与性能
【8月更文挑战第31天】本文详细介绍了如何在Tensorflow中实现多机多卡的分布式训练,涵盖环境配置、模型定义、数据处理及训练执行等关键环节。通过具体示例代码,展示了使用`MultiWorkerMirroredStrategy`进行分布式训练的过程,帮助读者更好地应对大规模数据集与复杂模型带来的挑战,提升训练效率。
59 0
|
3月前
|
消息中间件 存储 Kafka
微服务实践之分布式定时任务
微服务实践之分布式定时任务
|
15天前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
3月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
99 2
基于Redis的高可用分布式锁——RedLock
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】

热门文章

最新文章