好一点的网站,wordpress企业网站模板,对网页设计的简单理解,商城网站设计配色思想戳蓝字“CSDN云计算”关注我们哦#xff01;作者 | 温卫斌责编 | 刘晶晶源自 | dbaplus社群作者介绍温卫斌#xff0c;就职于中国民生银行信息科技部#xff0c;目前负责分布式技术平台设计与研发#xff0c;主要关注分布式数据相关领域。微服务兴起的这几年涌现出不少分布… 戳蓝字“CSDN云计算”关注我们哦作者 | 温卫斌责编 | 刘晶晶源自 | 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 transactionBusiness 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的特点在于业务资源检查与加锁一阶段进行校验资源锁定如果第一阶段都成功二阶段对锁定资源进行交易逻辑否则对锁定资源进行释放。应用实施成本较高。基于可靠消息最终一致一阶段服务正常调用同时同事务记录消息表二阶段则进行消息的投递消费。应用实施成本较低。具体到基于这些模型实现的分布式事务框架也多借鉴了DTPDistributed Transaction Processing模型。DTPDistributed Transaction Processing参考链接http://pubs.opengroup.org/onlinepubs/009680699/toc.pdf▲ 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/wikiSeata对MT以及TCC的支持亮点有限这两种模式更多是为了兼容已有应用生态。Seata团队画了一个的详细调用流程图对照此图阅读其源码会轻松很多。▲ 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前判断)。相比XASeata 虽然在一阶段成功后会释放数据库锁但一阶段在commit前全局锁的判定也拉长了对数据锁的占有时间这个开销比XA的prepare低多少需要根据实际业务场景进行测试。全局锁的引入实现了隔离性但带来的问题就是阻塞降低并发性尤其是热点数据这个问题会更加严重。2回滚锁释放时间Seata在回滚时需要先删除各节点的undo log然后才能释放TC内存中的锁所以如果第二阶段是回滚释放锁的时间会更长。3死锁问题Seata的引入全局锁会额外增加死锁的风险但如果实现死锁会不断进行重试最后靠等待全局锁超时这种方式并不优雅也延长了对数据库锁的占有时间。「Seata的引入全局锁会额外增加死锁的风险」参考链接https://github.com/seata/awesome-seata/blob/master/wiki/en-us/Fescar-AT.md5、其他问题1对于部分采用Seata的应用如何保证数据不脏读、幻读Seata提供了一个GlobalLock的注解可以提供轻量级全局锁判定的功能不生成undo log但还是需要集成使用Seata。2TC在逻辑上是单点如何做到高可用、高性能还是需要后续版本不断优化。3单机多数据源跨服务目前不支持。五、分布式事务的取舍严格的ACID事务对隔离性的要求很高在事务执行中必须将所有的资源锁定 对于长事务来说整个事务期间对数据的独占将严重影响系统并发性能。因此在高并发场景中对ACID的部分特性进行放松从而提高性能这便产生了BASE柔性事务。柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性要求来换取系统吞吐量的提升。另外提供自动的异常恢复机制可以在发生异常后也能确保事务的最终一致。基于XA的分布式事务如果要严格保证ACID实际需要事务隔离级别为SERLALIZABLE。由上可见柔性事务需要应用层进行参与因此这类分布式事务框架一个首要的功能就是怎么最大程度降低业务改造成本然后就是尽可能提高性能响应时间、吞吐最好是保证隔离性。一个好的分布式事务框架应用尽可能满足以下特性业务改造成本低性能损耗低隔离性保证完整。但如同CAP这三个特性是相互制衡的往往只能满足其中两个我们可以画一个三角约束基于业务补偿的Saga满足1.2TCC满足2.3Seata满足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开源项目越做越好福利扫描添加小编微信备注“姓名公司职位”入驻【CSDN博客】加入【云计算学习交流群】和志同道合的朋友们共同打卡学习推荐阅读漫画什么是希尔排序一次失败的面试复习一次一致性哈希算法Pandas中第二好用的函数 | 优雅的Apply程序员因接外包坐牢 456 天两万字揭露心酸经历限时早鸟票 | 2019 中国大数据技术大会BDTC超豪华盛宴抢先看阿里开源物联网操作系统 AliOS Things 3.0 发布集成平头哥 AI 芯片架构雷声大雨点小Bakkt「见光死」了吗真香朕在看了