分布式事务方案这么多,到底应该如何选型?

戳蓝字“CSDN云计算”关注我们哦!
640?wx_fmt=jpeg

作者 | 温卫斌

责编 | 刘晶晶

源自 | dbaplus社群

作者介绍

温卫斌,就职于中国民生银行信息科技部,目前负责分布式技术平台设计与研发,主要关注分布式数据相关领域。


微服务兴起的这几年涌现出不少分布式事务框架,比如ByteTCC、TCC-transaction、EasyTransaction以及最近很火爆的Seata。最近刚看了Seata的源码(v0.5.2),借机记录一下自己对分布式事务的一些理解。(3年前这类框架还没成熟,因项目需要自己也写过一个柔性事务框架)。

本文分五部分,首先明确分布式事务概念的演变,然后简单说下为什么大家不用XA,第三部分阐述两阶段提交的“提升”,第四部分介绍Seata的架构的亮点与问题,第五部分谈下分布式事务的取舍。

限于篇幅一些网上可搜索的细节本文不展开阐述(例如XA、Saga、TCC、Seata等原理的的详细介绍)。

一、分布式事务的泛化

提起分布式事务,最早指涉及的是多个资源的数据库事务问题。

wiki对分布式事务的定义:A distributed transaction is a database transaction in which two or more network hosts are involved.

不过事务一词含义随着SOA架构逐渐扩大,根据上下文不同,可分为两类:

  • System transaction;
  • Business transaction。

前者多指数据库事务,后者则多对应一个业务交易。

与此同时,分布式事务的含义也在泛化,尤其SOA、微服务概念流行起来后,多指的是一个业务场景,需要编排很多独立部署的服务时,如何保证交易整体的原子性与一致性问题。这类分布式事务也称作长事务(long-lived transaction),例如一个定行程的交易,它由购买航班、租车以及预订酒店构成,而航班预订可能需要一两天才能确认。为了统一对概念的理解,本文默认指的都是这类长事务。

分布式事务概念泛化的同时,也带来了一个技术问题,微服务下这类分布式事务的ACID该如何保证?是否仍然可以用传统两阶段提交/XA去解决?很可惜,基于数据库的XA有点像扶不起的阿斗,中看不中用。

二、为什么XA大家都不用?

其实也并非不用,例如在IBM大型机上基于CICS很多跨资源是基于XA协议实现的分布式事务,事实上XA也算分布式事务处理的规范了,但在为什么互联网中很少使用,究其原因我觉得有以下几个:

  • 性能(阻塞性协议,增加响应时间、锁时间、死锁);
  • 数据库支持完善度(MySQL 5.7之前都有缺陷);
  • 协调者依赖独立的J2EE中间件(早期重量级Weblogic、Jboss、后期轻量级Atomikos、Narayana和Bitronix);
  • 运维复杂,DBA缺少这方面经验;
  • 并不是所有资源都支持XA协议;
  • 大厂懂所以不使用,小公司不懂所以不敢用。

准确讲XA是一个规范、协议,它只是定义了一系列的接口,只是目前大多数实现XA的都是数据库或者MQ,所以提起XA往往多指基于资源层的底层分布式事务解决方案。其实现在也有些数据分片框架或者中间件也支持XA协议,毕竟它的兼容性、普遍性更好。

三、两阶段提交的“提升”

基于数据库的XA协议本质上就是两阶段提交,但由于性能原因在互联网高并发场景下并不适用。如果数据库只能保证本地ACID时,那么其中出现交易异常后,如何实现整个交易原子性A,从而保证一致性C呢?另外在处理过程中如何保证隔离性呢?

最直接的方法就是按照逻辑依次调用服务,但出现异常怎么办?那就对那些已经成功的进行补偿,补偿成功就一致了,这种朴素的模型就是Saga。但Saga这种方式并不能保证隔离性,于是出现了TCC。在实际交易逻辑前先做业务检查、对涉及到的业务资源进行“预留”,或者说是一种“中间状态”,如果都预留成功则完成这些预留资源的真正业务处理,典型的如票务座位等场景。

当然还有像Ebay提出的基于消息表,即可靠消息最终一致模型,但本质上这也属于Saga模式的一种特定实现,它的关键点有两个:

  • 基于应用共享事务记录执行轨迹;
  • 然后通过异步重试确保交易最终一致(这也使得这种方式不适用那些业务上允许补偿回滚的场景)。

这类分布式事务场景并不是微服务才出现的,在SOA时代其实就有了,常见的Saga、TCC、可靠消息最终一致等模型也都是很多年前就有了,只是最近几年随着微服务兴起,这些方案又重新被人关注了起来。

「Saga」参考链接:https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf

仔细对比这些方案与XA,会发现这些方案本质上都是将两阶段提交从资源层提升到了应用层。

  • Saga的核心就是补偿,一阶段就是服务的正常顺序调用(数据库事务正常提交),如果都执行成功,则第二阶段则什么都不做;但如果其中有执行发生异常,则依次调用其补偿服务(一般多逆序调用未已执行服务的反交易)来保证整个交易的一致性。应用实施成本一般。
  • TCC的特点在于业务资源检查与加锁,一阶段进行校验,资源锁定,如果第一阶段都成功,二阶段对锁定资源进行交易逻辑,否则,对锁定资源进行释放。应用实施成本较高。
  • 基于可靠消息最终一致,一阶段服务正常调用,同时同事务记录消息表,二阶段则进行消息的投递,消费。应用实施成本较低。

具体到基于这些模型实现的分布式事务框架,也多借鉴了DTP(Distributed Transaction Processing)模型。

DTP(Distributed Transaction Processing)参考链接:http://pubs.opengroup.org/onlinepubs/009680699/toc.pdf

640?wx_fmt=jpeg
▲ DTP模型

  • RM负责本地事务的提交,同时完成分支事务的注册、锁的判定,扮演事务参与者角色。
  • TM负责整体事务的提交与回滚的指令的触发,扮演事务的总体协调者角色。

不同框架在实现时,各组件角色的功能、部署形态会根据需求进行调整,例如TM有的是以jar包形式与应用部署在一起,有的则剥离出来需要单独部署(例如Seata中将TM的主要功能放到一个逻辑上集中的Server上,叫做TC( Transaction Coordinator ))

四、Seata架构得与失

今年初,阿里发布了开源分布式事务框架Fescar,后来跟蚂蚁TCC方案整合后改名为Seata,目前版本虽然只到0.6,但GitHub star已经过9k,一方面可见阿里在圈内推广能力,另外一方面也说明大家对阿里分布式事务框架的期待。

Seata的使用方式以及原理在其github wiki上已经阐述的很清晰,网上也已有很多源代码剖析的文章。接下来我们通过分析Seata AT模式原理,来看看它的亮点与问题。

「Seata的使用方式以及原理」参考链接:https://github.com/seata/seata/wiki

Seata对MT以及TCC的支持亮点有限,这两种模式更多是为了兼容已有应用生态。

Seata团队画了一个的详细调用流程图,对照此图阅读其源码会轻松很多。

640?wx_fmt=png
▲ Seata执行流程图

1、亮点

相比与其它分布式事务框架,Seata架构的亮点主要有几个:

  • 应用层基于SQL解析实现了自动补偿,从而最大程度的降低业务侵入性;
  • 将分布式事务中TC(事务协调者)独立部署,负责事务的注册、回滚;
  • 通过全局锁实现了写隔离与读隔离。

这些特性的具体实现机制其官网以及github上都有详细介绍,这里不展开介绍。

2、性能损耗

我们看看Seata增加了哪些开销(纯内存运算类的忽略不计):

一条Update的SQL,则需要全局事务xid获取(与TC通讯)、before image(解析SQL,查询一次数据库)、after image(查询一次数据库)、insert undo log(写一次数据库)、before commit(与TC通讯,判断锁冲突),这些操作都需要一次远程通讯RPC,而且是同步的。

另外undo log写入时blob字段的插入性能也是不高的。每条写SQL都会增加这么多开销,粗略估计会增加5倍响应时间(二阶段虽然是异步的,但其实也会占用系统资源,网络、线程、数据库)。

前后镜像如何生成?
通过druid解析SQL,然后复用业务SQL中的where条件,然后生成Select SQL执行。

3、性价比

为了进行自动补偿,需要对所有交易生成前后镜像并持久化,可是在实际业务场景下,这个是成功率有多高,或者说分布式事务失败需要回滚的有多少比率?这个比例在不同场景下是不一样的,考虑到执行事务编排前,很多都会校验业务的正确性,所以发生回滚的概率其实相对较低。按照二八原则预估,即为了20%的交易回滚,需要将80%的成功交易的响应时间增加5倍,这样的代价相比于让应用开发一个补偿交易是否是值得?值得我们深思。

业界还有种思路,通过数据库binlog恢复SQL执行前后镜像,这样省去了同步undo log生成记录,减少了性能损耗,同时对业务零侵入,个人感觉是一种更好的方式。

4、全局锁

1)热点数据

Seata在每个分支事务中会携带对应的锁信息,在before commit阶段会依次获取锁(因为需要将所有SQL执行完才能拿到所有锁信息,所以放在commit前判断)。相比XA,Seata 虽然在一阶段成功后会释放数据库锁,但一阶段在commit前全局锁的判定也拉长了对数据锁的占有时间,这个开销比XA的prepare低多少需要根据实际业务场景进行测试。全局锁的引入实现了隔离性,但带来的问题就是阻塞,降低并发性,尤其是热点数据,这个问题会更加严重。

2)回滚锁释放时间

Seata在回滚时,需要先删除各节点的undo log,然后才能释放TC内存中的锁,所以如果第二阶段是回滚,释放锁的时间会更长。

3)死锁问题

Seata的引入全局锁会额外增加死锁的风险,但如果实现死锁,会不断进行重试,最后靠等待全局锁超时,这种方式并不优雅,也延长了对数据库锁的占有时间。

「Seata的引入全局锁会额外增加死锁的风险」参考链接:https://github.com/seata/awesome-seata/blob/master/wiki/en-us/Fescar-AT.md

5、其他问题

1)对于部分采用Seata的应用,如何保证数据不脏读、幻读?

Seata提供了一个@GlobalLock的注解,可以提供轻量级全局锁判定的功能(不生成undo log),但还是需要集成使用Seata。

2)TC在逻辑上是单点,如何做到高可用、高性能还是需要后续版本不断优化。

3)单机多数据源跨服务目前不支持。

五、分布式事务的取舍

严格的ACID事务对隔离性的要求很高,在事务执行中必须将所有的资源锁定, 对于长事务来说,整个事务期间对数据的独占,将严重影响系统并发性能。因此,在高并发场景中,对ACID的部分特性进行放松从而提高性能,这便产生了BASE柔性事务。柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性要求,来换取系统吞吐量的提升。另外提供自动的异常恢复机制,可以在发生异常后也能确保事务的最终一致。

基于XA的分布式事务如果要严格保证ACID,实际需要事务隔离级别为SERLALIZABLE。

由上可见柔性事务需要应用层进行参与,因此这类分布式事务框架一个首要的功能就是怎么最大程度降低业务改造成本,然后就是尽可能提高性能(响应时间、吞吐),最好是保证隔离性。

一个好的分布式事务框架应用尽可能满足以下特性:

  • 业务改造成本低;
  • 性能损耗低;
  • 隔离性保证完整。

但如同CAP,这三个特性是相互制衡的,往往只能满足其中两个,我们可以画一个三角约束:

640?wx_fmt=jpeg

基于业务补偿的Saga满足1.2;TCC满足2.3;Seata满足1.3。

当然如果我们要自己设计一个分布式事务框架,还需要考虑很多其它特性,在明确目标场景偏好后进行权衡取舍,这些特性包括但不限于以下:

  • 业务侵入性(基于注解、XML,补偿逻辑);
  • 隔离性(写隔离/读隔离/读未提交,业务隔离/技术隔离);
  • TM/TC部署形态(单独部署、与应用部署一起);
  • 错误恢复(自动恢复、手动恢复);
  • 性能(回滚的概率、付出的代价,响应时间、吞吐);
  • 高可用(注册中心、数据库);
  • 持久化(数据库、文件、多副本一致算法);
  • 同步/异步(2PC执行方式);
  • 日志清理(自动、手动);
  • ......

六、结语

分布式事务一直是业界难题,难在于CAP定理,在于分布式系统8大错误假设,在于FLP不可能原理,在于我们习惯于单机事务ACID做对比。无论是数据库领域XA、Google percolator或Calvin模型,还是微服务下Saga、TCC、可靠消息等方案,都没有完美解决分布式事务问题,它们不过是各自在性能、一致性、可用性等方面做取舍,寻求某些场景偏好下的权衡。

「分布式系统8大错误假设」参考链接:http://%5Bhttps://en.wikipedia.org/wiki/Fallacies_of_distributed_computing%5D(https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing)

「FLP不可能原理」参考链接:html%5D(https://www.cnblogs.com/firstdream/p/6585923.html)

其实由于网络的不确定性,分布式下很多问题都是难题,最好的方案是避免分布式事务:)

最后回到主题,Seata解决了分布式事务难题了吗?看你最在意哪方面了。如果你希望业务尽量少感知,DB操作简单,那它会给你带来惊喜;但如果你更看重响应时间,DB写操作较多,调用链条较长,那它可能会让失望。最后希望Seata开源项目越做越好!

640?wx_fmt=png

640?wx_fmt=png

福利
扫描添加小编微信,备注“姓名+公司职位”,入驻【CSDN博客】,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!

640?wx_fmt=jpeg

推荐阅读:
  • 漫画:什么是希尔排序?
  • 一次失败的面试,复习一次一致性哈希算法
  • Pandas中第二好用的函数 | 优雅的Apply

  • 程序员因接外包坐牢 456 天!两万字揭露心酸经历
  • 限时早鸟票 | 2019 中国大数据技术大会(BDTC)超豪华盛宴抢先看

  • 阿里开源物联网操作系统 AliOS Things 3.0 发布,集成平头哥 AI 芯片架构!

  • 雷声大雨点小:Bakkt「见光死」了吗?

真香,朕在看了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/521415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

造大专计算机学历,广昌县职业技术学校计算机应用专业助您 掌握一技之长获大专学历...

——专题宣传报道之四:计算机应用专业计算机应用专业一直是广昌县职业技术学校开设的特色专业。该专业由一批经验丰富、专业优秀的教师任教,主要学习计算机操作、组装、网络应用、影视后期制作、平面设计、文档管理等理论知识和实训课程。特色一&#xf…

阿里云正式推出消息队列Kafka:全面融合开源生态

摘要: 在全面兼容Apache Kafka生态的基础上,消息队列Kafka彻底解决Apache Kafka稳定性不足的长期痛点,并且支持消息无缝迁移到云上。 近日,阿里云宣布正式推出消息队列Kafka,全面融合开源生态。在全面兼容Apache Kafk…

异常将上下文初始化事件发送到类的侦听器实例_Spring的Bean实例化原理,这一次彻底搞懂了!...

前言之前分析了Spring XML和注解的解析原理,并将其封装为BeanDefinition对象存放到IOC容器中,而这些只是refresh方法中的其中一个步骤——obtainFreshBeanFactory,接下来就将围绕这这些BeanDefinition对象进行一系列的处理,如Bean…

(需求实战_01) SpringBoot2.x 整合RabbitMQ_生产端

文章目录一、依赖配置引入1. 引入SpringBoot整合RabbitMQ依赖2. 生产者配置文件3. 主配置二、代码Conding2.1. 生产者代码2.2. 实体对象2.3. 测试类一、依赖配置引入 1. 引入SpringBoot整合RabbitMQ依赖 <!--springboot整合RabbitMQ依赖--><dependency><groupI…

全域图像搜索给你更精准的搜索体验

摘要&#xff1a; 2018飞天技术汇&#xff0c;阿里巴巴机器智能技术实验室的刘磊带来题为全域精准图像搜索介绍的演讲&#xff0c;主要从四个方面进行了阐述&#xff0c;第一部分介绍了图像搜索的基本概念&#xff0c;第二部分主要是讲解了图像搜索的技术架构及其优势&#xff…

【这些都不知道你就是个弟弟】Docker常用命令

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 程序员欣宸转自 | 企业博客责编 | 阿秃除了基本的docker pull、docker image、docker ps&#xff0c;还有一些命令及参数也很重要&#xff0c;在此记录下来避免遗忘。环境信息以下是本次操作的环境&#xff1a;操作系统&…

php 模数 指数 公钥生成_php实现JWT认证

什么是JWTJWT(json web token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息&#xff0c;以便于从资源服务器获取资源。比如用在用户登录上。JWT定义了一种用于简洁&#xff0c;自包…

SpringBoot2.x 整合RabbitMQ_消费端

这一篇讲解消费者 文章目录一、依赖配置1. 引入依赖2. 配置文件3. 主配置二、代码Conding2.1. 消费者代码一、依赖配置 1. 引入依赖 <!--springboot整合RabbitMQ依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>sp…

不断迭代,严苛细节,最终性能如何满足? 基于ELK的大数据平台实践分享

摘要&#xff1a; 在2018年Elastic Meetup 南京交流会中&#xff0c;来自云利来科技的涂海波为现场的听众带来了题为《南京云利来基于ELK的大数据平台》的精彩分享。在本次分享中&#xff0c;他首先进行了公司简介&#xff0c;然后介绍了数据分类&#xff0c;包括数据采集及数据…

cmd输入pip报错_pyhon3下pip安装使用教程(win10)

一、前言 pip 是 Python 包管理工具&#xff0c;该工具提供了对Python 包的查找、下载、安装、卸载的功能。官网下载比较慢,只有几k速度&#xff0c;大家如果还没下载python和pip可以到我的网盘下载。目前pip为v20.0.2版&#xff0c;pytho为v3.8.2&#xff0c;有最新版本会随时…

【小白集合】详解服务器内存和显存基础知识

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | Hardy责编 | 阿秃早期内存通过存储器总线和北桥相连&#xff0c;北桥通过前端总线与CPU通信。从Intel Nehalem起&#xff0c;北桥被集成到CPU内部&#xff0c;内存直接通过存储器总线和CPU相连。所以&#xff0c;在AMD采用So…

如何在机器学习项目中使用统计方法的示例

摘要&#xff1a; 在本文中&#xff0c;将通过十个实例介绍在机器学习项目中起关键作用的统计学方法。 统计学和机器学习是两个密切相关的领域。两者的界限有时非常模糊&#xff0c;例如有一些明显属于统计学领域的方法可以很好地处理机器学习项目中的问题。事实上&#xff0c…

云服务器 文件服务,云服务器文件服务

云服务器文件服务 内容精选换一换远程桌面协议(Remote Desktop Protocol&#xff0c;RDP)&#xff0c;是微软提供的多通道的远程登录协议。本节为您介绍如何使用RDP文件远程登录Windows云服务器。从管理控制台下载的RDP文件对应唯一的云服务器&#xff0c;当前RDP文件命名规则为…

(需求实战_03) SpringBoot整合RabbitMQ 关键代码、策略、模式讲解

这篇主讲管控台和测试 文章目录一、管控台配置1. 创建交换机2. 创建队列3. 交换机绑定队列4. 交换机查看绑定关系5. 队列查看绑定关系二、项目准备2.1. 启动测试方法2.2. 清空控制台2.3.一、管控台配置 1. 创建交换机 2. 创建队列 3. 交换机绑定队列 4. 交换机查看绑定关系…

c++ vector 初始化_什么?还不懂c++vector的用法,你凭什么勇气来的!

作者&#xff1a;良知犹存转载授权以及围观&#xff1a;欢迎添加微信公众号&#xff1a;羽林君前言今天继续肝C&#xff0c;一入C深似海。越学越有意思。今天给大家带来一篇cvector的介绍&#xff0c;难以置信这篇文章写了我三天&#xff0c;不过总算整理完毕&#xff0c;现在分…

突发!Python再次卫冕,Java和C下降,你怎么看?

2019年转眼已经大半&#xff0c;在近几个月的榜单中&#xff0c;Python已经走上卫冕的道路&#xff0c;并且与Java的差距拉得更远了一些。以往与Java常呈现你追我赶之势&#xff0c;而这一次则是直接相差了近10%&#xff01;Python的火&#xff0c;有目共睹。Python陆续登上了I…

NLP产品级系统设计模式

摘要&#xff1a; 在本文中&#xff0c;作者从六个方面描述了一些生产NLP系统的常见设计和部署模式。这些是团队为了使产品开发与技术、业务、战略和操作目标保持一致而必须做出的选择或权衡。 摘要&#xff1a;在本文中&#xff0c;作者从六个方面描述了一些生产NLP系统的常见…

2个vector如何合成一个_面试中如何做到不卑不亢,牢记2个要点

文│叨叨HR那点事(文章原创&#xff0c;版权归本作者所有&#xff0c;欢迎个人转发分享)面试的时候什么态度和面试官沟通&#xff1f;这个问题&#xff0c;就像一千个人眼里有一千个哈姆雷特一样&#xff0c;人人都有自己的意见和看法。有人说&#xff0c;面试嘛&#xff0c;当…

机器学习到底是什么?

摘要&#xff1a; 机器学习到底是什么东东&#xff1f;了解一下&#xff01; 关于机器学习最简单的定义来自于Berkeley所表述的:机器学习是AI的一个分支&#xff0c;它探索了让计算机根据经验提高效率的方法。 为了更深刻的理解这一定义&#xff0c;接下来我们将对其进行拆分…

修改服务器时间报错,修改服务器时间linux

修改服务器时间linux 内容精选换一换IPv6的使用&#xff0c;可以有效弥补IPv4网络地址资源有限的问题。如果当前云服务器使用IPv4&#xff0c;那么启用IPv6后&#xff0c;云服务器可在双栈模式下运行&#xff0c;即云服务器可以拥有两个不同版本的IP地址&#xff1a;IPv4地址和…