粉丝3668获赞1.9万

呃,哈喽,今天给大家分享一下 say 塔。首先我们来看一下它是一款开源的分布式事务解决方案,然后致力于在微服务价格下提供哦,简单易用的分布式事务服务。好,然后我们来看一下我们的一个案例呢,在这个地方我们也写好了一个小的案例哦,在这里 这里有三个服务,一个订单服务和我们的一个库存,还有账户服务。然后当用户下单时候,会在我们的一个订单中订单服务创建一个订单,然后远程调用我们的一个库存来扣减商品的库存, 然后再调用他的一个账户服务,扣减用户的一个账户里面的一个余额。最后在订单服务修改订单状态我已完成。首先这一个的一个架子我们已经搭建好了,首先我们来看一下这里有一个尔康特,还有一个 order, 还有一个 store storage。 然后也是在我们的一个数据库里面,这里有三个数据库,同样也是一个 account, 一个 order, 一个 sorry。 进来我们来看一下这三个,呃,库里面的一个表,有一个 account account。 首先用户有一千块钱,然后订单, 订单这里呃是没有的,因为我们目前还没有下单,对吧?然后在我们的一个 storage, 就是我们的一个库存有 iphone 十二,有一百台,一百个, 好, ok, 然后我们嗯来看一下他的一个流程,在我们这里首先我们的一个拉克斯是采用二点二点零的这一个版本,然后我把当前的一个 say 他 sovere 已经注册到我们的一个拉克斯上面来。首先我们来看一下 它的一个流程还是相对比较简单,这里我们在本地搭建了我们的一个 lucks, 然后同时也是本地安装了一个 say 他 sorry 这一个服务, 并且注册到我们的一个拉克斯上面已经去了。接下来我们本地启动三个服务,现在三三个服务都给启动完成。接下来我们在我们的一个订单这个服务来调用一下他的一个下单接口。 首先我们直接用这一个 id 里面自带的一个 hdb 请求 client, 然后我们点到这里来,然后这里我们已经写好了一个这里下单接口,然后同时它的一个是用户 id 和一个商品和我们的一个数量, 好,我们来发送一下请求,在我们这里,好,现在已经报了一个五百,对吧?我们来看一下为什么报五百。在我们这里有一个下单,然后下单的时候我当前没有加 global transition 的一个注解,然后我们来看一下它的一个逻辑, 就是我们创建订单,然后远程调用扣减库存,然后扣减一个用户的一个余额,接下来修改的状态为一,然后这里报了一个异常,对吧?报了一个异常,我们来可以看一下,大家都知道这一个白日任务弱, 这里好, ok。 然后我们来看一下他都报了,报错了,对吧?然后看一下他,他的一个执行情况, 九百九,他报错了,这这一个程序,他还扣减了他的一个账户余额,然后我们看一下他的一个库存,啊,库存,库存也扣减了十,对吧?然后我们看一下订单, 订单他没有更新他的状态,唯一说明这一段程序是有问题的,在一个呃微服的情况下,好,我们来修改一下,再让我们开启我们的一个全局是 就是我们的一个分布式失误,好,我们来再来执行一下这一段的一个程序,在我们这里同时把他的一个 total mot 给他给设置成一千,然后接下来我们把库存同样也是设置成一百,然后把我们订单给清空一下, 好, ok, 然后我们重启一下我们的一个订单服务, 好, ok, 然后启动完成,启动完成之后他会注册到我们的一个呃 notes 上面来,现在,好,已经注册上来了,我们可以看一下刚刚注册上来他是 是十点三十七分,对吧?十点三十七分,我们同样来发送一下请求,在这里 他肯定也要报五百,对吧?但是他的一个事物得到了一个控制,我们来看一下订单有没有创建好,好,现在订单是没有的,然后我们看一下库存,库存也是一百个,然后我们的一个账户 好,一百个,然后这就是完成了在我们的一个微服务情况下的分支事务的一个使用。 ok, 然后觉得有用的可以帮忙点点赞,点点关注。然后如果想要这一份圆码的话,可以进一下我的一个粉丝群,或者啊直接进入我们的一个自信球,自信球里面有完整的相应的像中间键的一个搭建, 在这里,我们可以直接星球里面可以下载我们 c 塔二点二点零和一点六,然后直接可以启动,然后并且有原码,相应的文档都是有的, ok, 谢谢大家。

我们说到分布式事务呢,比较常见的就是这个插爱模式啊,基于数据库的事务,还有呢是 tcc 啊,基于补偿模式。那么还有一种呢啊,是这个 at 模式啊,用的也很多是阿里的这个 ct 推出的, 那么这两天呢,正好有一个分布式事务要写,我就用了一下这个,呃, it 模式还挺好用的,真的,就像这个 c 台文单上写的那样,没有做任何的代码侵入,只要引入一些啊简单的依赖,添加一个格罗波全赛克声哦,这个柱姐 对吧,那么所以他管理器呢,就帮你把这个事务给做了,确实呢,还挺方便的。那么说到这个 at 模式的原理啊,啊,也很好理解啊,同样也是两个阶段,一阶段呢就是提交数据啊,比如说你下单 哦,涉及到了 qq 存啊,又涉及到了出现订单,那这个时候呢,我们通过格罗波这四个神喽,这个柱姐呢啊,他就做了这个 aop 啊,前面拦截对吧,你的所有的搜口啊,每一个分支对数据库的操作都会记录在这个安都 logo 里面, 但是这个 log 呀,啊,不是数据股级别的,这个回滚日制,它是 c 塔自己解析的这个搜索语句啊,形成的日制,详细的记录了每一个步骤啊,这个是一阶段, 那么二阶段呢,就是判断每一个分支是不是都成功了啊,如果都成功了呢,那么之前写的 anglelog 回滚日制呢,就直接删除啊,全局所示范掉,那么其他的操作啊,可以进来,那么如果有一个分支失败啊,那么就直 行对应分支的安多罗尔的回款日制,原来扣减的库存,你得恢复到原来的数值,创建的订单呢也得取消掉,这个就是 at 模式的一个原理,核心呢就在于啊,代码没有侵入啊,只通过注解的方式就能够分析出数据库做了什么事情 啊,并且呢形成了一个啊叫做安都 logo 的日制啊,这些都是在 c 的层面来做的 啊,虽然很简单啊,也很方便啊,用的很爽,但是呢还是啊有一些问题的,比如说一个师傅在运作啊,在下单,在扣库存啊,在创建订单,这个时候呢,如果有另一个七线城过来, 这个时候呢是不让他读的啊,容易发生单独,怎么解决呢? ct 呢,就直接左侧了,所以呢确定还是很明显的性能不是那么的好 啊,在当前事务没结束的情况下面,全局所会把其他的县城主宰在门外,所以呢他其实是牺牲了一定的这个并发能力 啊,如果在一些这个性能要求比较高的场景,还是推荐大家用一些这个其他的补偿型的失误模式,比如说像这个 ttc, 像萨嘎,对吧, 虽然侵入代码,但是在并发性能上面要好很多。好了,本期的视频呢就这些了,如果您对本期的内容呢,有任何疑问,欢迎大家在评论区给我留言,谢谢大家!

说说 see 卡的实现原理,那 see 卡呢,它有四种模式我们应该都知道吧,有 a t t c c, saga 和 x a 四种模式,那每一种模式呢,他们的实际原理肯定都各不一样,我们也不可能呢,每一种模式都给面试官去介绍一遍对吧?那我们呢,就可以以最常见的这个 a t 模式为例呢,去给面试官进介绍关于这个问题的详细文字版,我已经整理了一份八十万字的 drive 面试大全笔记,放在视频的最后面,坚持看完一定对你有帮助。 那其他三种,如果同学们想详细的去了解啊,可以去看一下我们的图林高级架构式课程,好吧,里面呢就对这其他三种模式呢,都有详细的去介绍。 当然针对面这道面试题呢,我们也只需要通过这个最常见的 a t 模式呢,来给面试官进行解答就行了,因为他也不会去考你这种 saga 呀, x a 呀这种冷门的模式,他最主要呢是 希望听到你对这种分布式失误的统一解决方案。那分布式失误呢,我们通常都会采用这种二阶段提交的这种方式来进行实现,不管是哪种方式啊,不管是我们刚刚所说的 a t 啊, d c c 啊,沙嘎啊, x a 啊哪一种模式,它都是采用的二阶段提交。 因为分布式失误,他不像我们的这种本地事务啊,他一个阶段是完不成的,他必须要分两个阶段去完成,第一个阶段呢,叫做准备阶段,他需要呢通知每一个这个分布式失误的参与者,也都是我们的微服务,你首先要准备, 准备完了之后呢进行提交或者回滚,这是第二个阶段,所以说分布失误呢,他要分两个阶段完成,也就是我们所谓的二阶段提交的方式。那我们的 cta 呢,不管是哪一种模式啊,他都是由这三个角色来进行协调完成的, 所以说这三个角色呢,我们也得知道。首先第一个是 t c, 这个 t c 呢,它是事物协调者,它主要呢协调我们每一组这个分布式事物, 知道吧?并且呢有效的隔离出来,给他们进行隔离。然后呢管理每一个分支事物,这是我们的事物协调者,他的一个作用,他呢告知每一个分这个分支事物是不是都准备好了呀? 准备好了,然后呢我会告诉你们什么时候提交,什么时候回滚,要是这个事物协调着,就相当于对一个这个事物总管的这样的一个角色,主要是呢,用来告诉每一个分支事物你们应该干什么?好吧,那么这个 tc 呢,它其实就相当于是我们 c, 他的这个服务 ok。 然后呢是 t m, t m 呢,是十五发起者,这个 t m 跟 m 呢,它都是运行在我们的微服务端,也就是我们的 c 塔的客户端。 那它呢,首先来看一下 t m 啊,它是事物发起者,也就是说呢,它会在这个事物开始的时候呢,去通知我们的 t c, 然后呢当我的失误完成了之后,当我的本地失误完成了之后呢,他也会通知这个 tc, 那么当我的本地失误出现了问题呢,他也会去通知 tc, 告诉 tc 呢,你要回滚了,或者告诉 tc 呢?可以,我,我这个本地失误呢已经 就绪了,可以提交了,好吧,它主要是这个作用,然后呢 m m 呢是事物资源,它主要呢管理我们这个通过事物当中的这些事物相关的资源,好吧,一些资源信息, 那么我们来看一下这个 at 模式它到底是怎么样的,一个执行原理,一个怎么样的过程。首先这个 t m, 也就是我们刚刚所说的这个失误发起者啊,它的失误发 发起什么肯定会由他最先的,像这个 t c, 好吧,你可以把这个 local transaction 这个本机失误呢当做是这个 t m, 一开始呢,他会首当其中的向这个 t m 呢去发起一个就开启申请啊,我要去开启一个全局失误了。 然后呢这个 d c 呢,他就会去创建一个全局输入,并且生成一个全局唯一的这个 x i d, 这个 x i d 呢,他就贯穿在我们整个微服调用链路当中来进行传播,保证了我们这一组微服务的 就是创在一个分布式当中,知道吧?并且呢根据这个 x i d 呢,也可以有效的去隔离每一组这个分布式式物, ok, ok, 那么这个 x i d 传奇输入创建好之后呢,就开始去运行我们的这个数据操作了,假设我们现在 去运行一个更新操作,那么首先啊,会有我们的 m 就是这个事务资源者,他呢会去解析这个 circle, 得到你这个 circle 是它的什么类型?我们这个 circle 是 update, 对吧?那么它会得到 update 的类型,然后得到你的表啊,得到这些条件,那么这个阶段我们叫做解析 circle 的阶段,解析完,那解析这个是用来干嘛呢?它主要是用来查询这个 circle 执行前的一个镜像和 circle 执行后的镜像, 他会把你这个 update 的运行之前的这个数据啊给你查出来,也就是他之前不是解析到了条件,解析到了表吗?那么他可以根据你的条件啊,根据你的表啊给你生成一个啊数据,比如说 select from product 是它上一步解析出来的表,然后这个是它上一步解析出来的条件,那么通过这个锁口呢,它就 能查询到你这个 circle 执行前的一个径向前的数据, ok, 那么查询到了径向前的数据,并向前 镜像前数据查询完之后呢,去执行这个具体的数据操作,好吧?然后执行完之后呢,再去查询一遍,再去根据这个 circle 查询一遍,也就是镜像后的数据了,也就是更新之后的数据了,镜像后的数据,那这个镜像前跟镜像后的数据我们猜一下有什么用? 他是不是如果我们后续如果要做回滚的话,是不是就可以根据这个镜像前的数据给他逆向的生成一个 update 的语句,给他重新的给他回滚回去就行了呀,对不对?所以这就是这个镜像前和镜像后的数据啊, 那么然后啊,这个镜像后的数据查询完出来之后呢,他会把这些数据插入到一个叫做安 都 log 的一个表达中,好吧,也就是镜像前的数据,镜像后的数据插入到这个安都 log, 好吧,然后在提交之前我们的 i m 呢,它会将我们当前这个事务分支呢去注册到,像这个 t c 呢去注册,好吧? 然后呢申请这个 product 表,我当前这条数据呢,进行全局锁,那么其他的这个由斯塔管理的这个全局这个分布输入呢,就不能去操作我当前的这条数据了? 第二呢,就避免了我们这个脏读啊,脏写的这一系列的这些问题,好吧,会给娜娜管理一个全剧索, 那么接下来呢,会执行同意,他也就是把我们的这个插入到这个 anneloc 的表啊,以及执行到这个呃,业务当中的数据啊,统统都进行提交好吧,提交入库,然后最终呢,我们的 t m, 我们的本地失误,也就是这个 local transaction, 它呢会向 t c 发起一个针对这个 x i d 全局提交或者回滚的决议, 也就是说呢,他会将我当前这个本地失误的提交结果啊,上报给 t c, 也就是我当前这个本地失误,他如果执行成功了,就说明我已经准备就绪。如果我当前这个本地失误,他提交失败了,那么是不是要告诉 t c, 你可以进行回滚了呀?我这里有一个失败了,肯定的所有的都失败,对不对? ok, 那么如果每一个分支失误,他都最后给 t c 给他 就是发起发起一个上报,告诉 t c 成功了,那么肯定最终呢会执行提交的二阶段操作。那么如果有某一个分支失误,他向这个 t c 提交了失败的这个报告,那么二阶段呢,他就会执行 回滚的操作。 ok, 我们先来介绍一下提交啊,那么当我们的,当我们的这个 t c 收到分支的所有的请求都提交成功之后呢? 那么我们这个 t c 啊,它会把请求呢放入到一个异部队列当中,然后呢马上返回一个成功的结果给 t c 知道吧? 然后异步呢,他会去执行找到你之前插入到 antolog 的这些镜像前,镜像后的这个数据,根据你当前这个分支 id 啊,因为因为之前插入这条数据的时候呢,插入这个 antolog 的时候呢,他也会 携带这个分支 id, 知道吧?那么现在找的时候呢,肯定也要根据这个分支 id 呢进行找出来,找出来之后呢,删掉这个安多 log 记录就 ok 了,这就是提交,提交非常的简单。好吧,提交说白了就是把这个安多 log 回滚的这个镜像前 向后的数据给他杀掉,就是二阶段提交他非常的简单。那么二阶段回滚呢,他的步骤又稍微多一点,那么当我们的 tc 收到某一个分支,他要进行回滚的请求的时候呢, 我们呢就会开启一个本地事务,执行如下操作,然后呢,他会通过 x i d 和这个分支 i d 找到安多洛的数据,也就说呢,我需要拿到我的这个镜像前后的数据,好吧, 拿到镜像前的数据,我刚说了可以进行回滚操作,对不对?然后拿到镜像后的数据呢,跟我当前的数据进行比较,干嘛要比较呢?直接回滚不行吗?干嘛在回滚之前我还要比较呢?其实他这个比较啊,是为了 判断一下当前这个失误当中的数据是不是,是不是被别的,是不被当前全局失误败的动作去做了修改。 那么如果做了修改,如果他判断你镜像后的数据跟你当前修改的数据不一样的话,就说明呢,被当前事物之外的动作做了修改,也就是我们所谓的出现了三组, 那么当出现了单独啊,一般呢,我们会转人工去处理啊,但是一般这得看你具体 c 塔对应的这个策略的配置是什么,一般呢会转人工处理,也就说呢,因为 c 塔他无法感知这个彰显是如何发生的, 所以此时呢,他只会打印一个日志和触发异常的通知,告知用户呢,需要人工去接入,这是他默认的一个策略,知道吧? 也就是说呢,他会拿到这个镜像后的数据,跟我们当前的这个数据进行对比,如果对比不上呢,他又会出现所谓的脏血,那么就会打印日志和触发异常, ok, 那么如果检检查这个镜像后的数据跟当前的数据没有 发生变化,也就是没有脏写啊,那就简单了,直接呢,根据这个 undo log 的这个镜像前的数据,这个逆向的生成一个 circle, 就比如说你之前,你之前不是 update, 你之前不是 update 把这个 name 改成 g gts 吗?然后我不是在把这个镜像前的数据给查出来了吗?对不对?那我把这个镜像前的数据给它逆向的生成一个 update, 我给它回,回,回去不就完了吗?对不对? 比如说他没有出现三弦,也就是说验证完这个镜像后的数据没有问题的话,他就会拿到你的这个镜像前的数据,然后逆向生成一个回滚的 circle, 好吧,然后呢?删除 angle log, 最终呢提交, ok, 然后呢最终将我们的分支事物呢告知这个 t c, 我已经回这个回滚的这样的一个结果,告诉 t c, 好吧,这就是我们的 at 模式的一个 c 塔的执行过程。好吧,那么不管 哪种哪种模式啊,我刚说了,他都是采用的二阶段提交,然后都是由这三个角色来进行协调完成的,有可能呢,就是这些步骤,不同的模式,这些步骤不一样而已。 ok, 好吧,这就是我们 c 塔的实现原理。 nice。


说人话中,实战讲干货。你好,欢迎来到 it 老齐的架构三百讲,我是你们的 it 私人顾问老齐。到今年呢,我从业已经十八年了,一直做扎瓦与架构的研发工作,今年呢,是我创业的第一年,目前呢,已经录制了十多门与编程架构相关的课程, 同时我还会提供点对点的简历优化、模拟面试、 offer 选择、解决方案、架构指导等服务。总之呢,只要是我有经验的,能给兄弟们帮上忙的信息呢,我一定坦诚相待。有需要的小伙伴呢,可以看一下评论区或者我的个人描述,希望能用我的经验帮你少走弯路,找到更好的工作。 今天咱们来聊一聊,在咱们整个分布式事物中,有一种叫 x a 的方案,那么作为 x a 方案呢,现在很多互联网的架构师呢,对他嗤之以鼻,其实啊,在我看来,很多时 都是在过度设计。那今天呢,我们就联合阿里 c 他呢,看一下 x c 方案是什么,以及阿里 c 他他是如何对 x c 的方案进行支持的。 首先呢,咱们来了解一下,到底什么是 x a 方案呢? x a 方案呢,也称 x 规范,是 x open 组织所定义的一种官方标准,它用于说明分布式事物的处理模式。 那作为 xc 方案呢,也是典型的两段式的处理,在我们著名的阿里巴巴的 cta 分布式事务解决方案中,在近期的版本呢,也对 xa 呢进行了支持,所以在日常开发中, 作为 x a 呢,也可以是我们在使用 set 中的一种选择。那到底 x a 方案是怎么回事呢?说白了呀,就是 x a 方案呢,作为业界 的一种分布式事物的标准,主流的关系型数据库,买 circle oricle 啊 p circle 等等等等,对他呢都有一些良好的支持。所以呢,在我们开发的时候,只要这个数据库是支持 x c 方案的,那作为阿里巴巴的 cta 这个分布式事物的中间线, 它就可以支持这个数据库,并提供相应的服务。那么作为 x a 到底是怎么回事呢?其实啊,非常的简单, 作为 x a 呢,它也是分成了两个阶段来进行处理的。首先左边的阶段叫做 prepare 阶段,也就是我们的准备阶段。作为准备阶段中呢,他会有三个角色, 一个叫 t m, 也就是事物管理器,说白了这个事物管理器呢,就是用来划分当前我们分布式事物的边 边界和范围在哪呢?这个是这么说,有点抽象,一会咱们看一眼代码你就明白了。而第二个 rm 就是资源管理器,他说白了他就是负责针对具体的数据库进行操作的。这样的一个角色, 那还有一个叫 t c, 也就是全局事务的协调者,用于事务注册以及全局事务的提交或者回滚的处理。 那么咱们结合场景来看一下假设呢,现在我有一个业务逻辑叫做 business service, 他呢是用来创建订单的,要知道创建订单往往需要由多个业务组合在成,也就是另外一个系统的订单服务下呢,来进行订单的新增。而除此以外呢,作为订单创建以后, 那对应用户的余额要进行减少,那这时又会涉及到 account 账户系统,那从我们设计的时候,原本的订单系统有一个团队来维护,一个账户系统有一个团队来维护, 同时作为我们这个商城的入口呢,他也有另外一个系统来维护,这是一个典型的分布式系统。那如何保障所有的 outer service 和 account service, 它要么全部提交,要么全部回滚呢?这里就可以考虑利用 x a 方案来实现了。 x a 方案下,只要我们数据库能够支持 x a, 那作为 set 这个中间键,它就可以进行支持。 那我下边来说一下它的处理过程。首先呢,作为第一个阶段 t m 下,它在启动的时候,创建订单前,会 自动的向 t c 也就是 set 的服务器发起一个注册全局事务,说明我要开始全局事务干活了。 紧接着商城呢,会去远程调用这个 order service, 也就是 r m 这端来完成 creat 订单创建的这样的操作。要知道,订单创建本质上就是在我们订单数据库中新增一个 insert 语句,完成订单信息的插入。 那么在 r m 这端,它要完成数据插入前,会自动的要和这个 t c c 它 server 呢?完成一个分支事物。 没错,在我们的分布式事务中,作为 t m 是控制全局事务,说明总的事情要开始干了,而分支事务则对应了这里,每一个步骤他都对应一个分支事务,他 也是会需要向 sata 来进行注册的。那作为 business service t m 呢?在调用完 creat 方法以后,完成了对于 order cool 的一个新增的操作。注意,这里 在进行新增操作时,只是去执行了 insert in two 语句,它并没有进行提交, 此时执行完死口是不提交的。而且作为另外一边,作为咱们这个账户库呢,他也是要 根据用户的编号去扣减余额,那他就会调用 account service 的 reduce 这个方法来扣减账户余额。 那么作为 account 库,它里边当然是用更新 update 语句来将指定账户的余额进行扣减。作为这两个 circle, 它都是只是完成执行,但是 是不会提交。在这个处理过程中,一旦 order service 点 create 方法对应成功, account service 点 reduce 方法,那当前就认为第一阶段处理完成了,那紧接着就会进入第二阶段。第二阶段的话,是由刚才的 business service 呢向 t c 呢,也就是 cd server 下达一个全局提交的命令,当下达全局提交以后,由这个 t c 呢主动地向两个 r m 这端来推送一个 commet 命令。 当卡密特命令收到以后,刚才我们这两条 circle 语句不是没提交吗?现在呢,都进行提交就完事了,那整体呢,就保证了我们数据的一致性。那在这个过程中有一个分支情况,假设我们 order service 处理成功了,但是 account service 因为余额不足处理失败,需要回滚的话,那么作为第二阶段呢,他下达的就是全局回滚的操作, 此时 t c 呢,会向 r m 下达 robec 命令,然后 r m 把刚才新增的 insert 语句给回滚掉就完事了。因为在这个过程中,所有的处理都是基于数据库的事物特性来完成的,所以呢,是可以保证整体 数据库的原子性,要么这些数据全部提交,要么这些数据全部回滚,这就是我们 xa 方案它的一个优势所在,可以保证我们数据的强一致,那这么说你应该了解了关于 xa 方案的执行流程,但是 xa 方案它在执行过程中 代码长什么样子,如何和 cat 结合来使用呢?我们来看一下代码就明白了,作为 cat 呢,它封装度是非常高的,在我们开发的时候,甚至你都可以把它理解成是一个本地系统来进行调用就可以了。 比如说咱们先来看 t m 端, t m 呢就是定义事物边界,也就是我们接入的入口这端, 在进入入口中,这里有个 purchase 购买的这样的一个方法。在 purchase 中有一个 sita 独有的注解叫 global transactional, 它的含义是开启全局事务。那么这里它的一个典型特性是,当开始执行 purchase 的时候,就自动的会在这个 business service 中向刚才的 t c 来下达一个注册全局事务的指令, 然后呢,程序进入运行,如果这个 protest 方法执行成功,则自动的进入二阶段去下达全局提交的命令。如果在中间过程任何一个执行步骤抛出了运行时的异常,他就会自动的向 tc 下达全局回滚的命令。 这个过程完全是由 seta global transactional 来给我们完成的,我们不需要额外的去控制。那么在这里每一个步骤呢?其实你可以看到稍微懂一点 spring club, 你可以发现这个通过 open fin 的方式呢,进行远程服务的调用,上面调用的是 account fin, 而下面都用的是 order fit。 我们先来看一下 order 这个服务,在 order 服务中啊,也就是每一个具体操作数据库的地方, 它呢需要做两件事,第一件事呢,就是在 r m 这端操作数据库之前呢,它需要 我们对现有的数据源 datasos 呢来进行一个包装,例如在演示代码中,这里它使用的是阿里巴巴著名的数据库连接词照一的来进行的处理。那么在下边你发现没有,在 构建 data sauce 的时候,它呢在原有的 joy the data sauce 中去 new data sauce proxy xa, 通过对原有数据员的包装呢,可以实现自动的这个分支事物的注册以及接收分支事物的提交或者回滚的操作,这一步非常的重要,因为他对我们原有的数据员进行了扩展。那么第 第二个呢,就是在我们业务方法中, order service, 那当然是用来进行新增操作的,所以你在实际开发的时候,就使用标准的声明式事物,通过 at transactional 描述这个业务方法,然后执行 insert in two 语句就完事了。 那在这个过程中,因为底层呢,都是基于数据源和各种各样的底层的 g, d, b, c 来实现的,所以你在数据操作时使用 hibernate 或者使用 my batis 都是没有任何影响的。哎,该怎么操作?怎么操作? 那当当前的这个 create 方法执行完了以后,那我们原有的 business, 那我们原有的方法呢,它就会向后执行,例如进入到了后面的这个 account service 扣减余额的这个部分,扣减余额部 粉在配置上也是一样的,还是要通过 data sost proxy xa 呢来进行对数据源的扩展和包装。然后呢,在这个 自己的业务代码中 account service 账户服务吗?那你就对从前台传入的用户编号和金额呢来进行一个相应的扣减就完事了。 那整体的逻辑我这么说你应该就明白了, t m 呢,就决定了事物的边界。确实,这里体现出的一个方法,方法执行成功,那自动的进行全局事物的提交。在二阶段的时候,由 seta server 主动地向各个 i m 来发起 comet。 如果这个方法中间有任何一个节点出现了问题,则会出现 robot 回滚的操作。我们之前处理的数据,比如说 insert, in to 或 或者是这个 update 语句,它都会被 robot 还原。因为作为 x a, 在一阶段我们执行了这个 circle 语句以后,它是不会立即提交的。注意,是不会立即提交的,它会在我们数据库的事物里边给 留存起来,等待 sata 下发的 comet 或者 robuck 指令,再完成后续的写盘或者回滚的操作。这便是 x c 方案它的一个处理逻辑所在。 那么针对于 x a 呢?它到底在日常工作中是怎么样的呢?它有什么好处和劣势呢?好处和劣势都非常明显,只要我们找到适合的场景, x a 仍然是一个优秀的选择。首先第一个,它是基于 c p 的设计,属于强一致的,尤其对数据 敏感性比较高的重要数据,采用 x a, 你会保证它不会出现丢数的情况。 第二个就是因为主流数关系型数据库呢,对 x a 呢,都是有支持的,属于业界标准了,它非常的稳定,而且支持广泛,不会像其他的民间自发的分布式事务方案一样,这个支持那个不支持,很恶心。 作为 xa 呢,大多数的主流的关系型数据库都是支持的,而第三种呢,就是二阶段提交呢,哎,他实现简单粗暴,也是人们最容易理解的一种分布式方案,对于代码的变化呢,也是非常少的,属于成熟稳定的。 那么 x a 的方案它的劣势呢,其实也是同样的明显的,第一个就是因为所有的操作都是基于数 数据库事务来进行的,我们新增的和修改的代码呢,都是在数据库的事务区里边来进行的操作, 所以在我们最终数据没有提交之前,这个事物里边的行呢,就会被夯住,也就是会被锁住。就像刚才我们对用户来进行余额更新的时候,那阶段一呢,那他就会在提交之前, 把这个 user id 等于对应编号的这行数据呢给夯住,那此时任何其他连接要对这条数据进行写操作的时候,都会被夯住,进入阻塞的状态,一旦阻塞,性能不就下来了吗?这是第一个情况, 而第二个情况是协议阻塞,因为在我们进行数据处理的时候, 在底层呢,其实建立的是一个长连接,那么这个长连接他在我们提交以后就会一直处于等待接收 set 反向推送 comet 或者 robot 命令, 那在这个过程中,如果我们的网络不稳定,或者呢这个呃收发的时间过长,在网络层面上他也会出现一个高延迟。同时作为常连接,在收到 x a 卡 meet 或者 x a robec 这种全局提交或者全局回滚命令之前,他都是处于阻塞等待的状态,这对于我们网络这个连接的利用率也是一个问题。 同时呢,还有一个更加严重的情况,我们举个例子,现在呢,我们来看一下假设呢,我们在 处理过程中,第一个数据库,它呢? auto service 正常处理成功,而第二个 account service 呢,甭管是因为什么原因,有可能是 c 口执行慢,也有可能是其他什么原因好,那他的网络不稳定,时断时续的,那作为 t c, 在建立好这个连接以后,他会尽量的去尝试完成这个工作。 假设完成这个 account service, 前前后后连同事啊带各种操作用了五秒钟时间,这就意味着前面已经处理完的 outer service 中,某一条数据呢,可能进入了长达五秒的被锁定的状态, 所以因为网络的原因,也可能会导致我们数据在操作时出现阻塞,这种情况下也是比较可怕的。所以说 啊,作为这个分布式事务下,强一致,他的代价就是低性能,这是我们无法避免的事情。 那同时呢,还有一个劣势,就是如果你使用了 x a 方案,就必须所有数据库都支持 x a, 否则你中间有一个不支持,那我们整体的全局事务就没法保证。 可是现在在互联网的这个大环境下,很多 o l t a p 数据库,也就是分析型的数据库呢,它本身就是不支持事物的,它就更提不上去支持 x a 了。那在这种 no circle 啊,大型渠道的互联网背景下,那你使用 x a 不就是跟自己找不自在吗? 所以说,这也是为什么在大多数企业互联网,尤其是靠前台的应用下,那使用 x a 几乎销声匿迹的主要原因,但是 xa 呢,仍然不失为一个很好的选择,尤其是在这个银行领域,因为大家都知道,银行领域在内部呢,实际上并不是一个高并发系统。你可能会觉得,哇,银行一天这么多人在用,他的并发量会很高吧?其实不是的, 银行他的数据量很大,他的并发量其实往往并不是特别高。同时呢,作为除了核心业务系统以外,他的这种数据冲突也是相对较少的。什么意思呢?你比如说我们像刚才什么情况下会出现严重的这种啊 行等待所等待的状态呢?就是我们如果说同时有一百个人给我这个账户来转账的话,那么如果采用 x c 方案,强一致,前边人转不完,后边人我们就 一直处于阻塞的状态,这也是基于 c p 强一致的一个问题所在。但是你是想过没有,除非非常特殊的业务,像什么结算账户,好一天几百上千笔向同一个账户进行结算, 除了这种极端情况下,大部分的账户,像你的我的账户一天能有多少笔收款和入款呢?针对于这个数据,我们写冲突的可能性又有多大呢? 所以这种可能性针对于我们,比如说像银行个金出啊这样的业务场景呢,就是非常适合的,因为他的数据冲突相对比较小,同时呢, 在银行体量中,他的这个并发量按照现在互联网对比来说也属于低并发。因此像这样的应用场景呢,是适合 x a 的。而且大家也要明白,咱们现 在天天都在喊高可用高并发,可是真正的你想过没有?真正高并发的系统有多少啊? 那所以在我们自己来进行业务开发的时候,你为了去保证数据,所谓的这种呃高效的执行采用了 a p 方案,或者采用了一堆补偿方案,但是你想想真的有这个必要吗?如果我们是在低并发或者数据冲突较少的情况下, x a 真的是一种非常好的选择,尤其是在企业级游泳时,这是一个很好的处理方案。好的,那我费了半天口舌。那如果你能真的听到这里,那说明真的是真爱粉了,那给个三连不过分吧。谢谢兄弟。

真的是太可喜可贺了!近日,分布式事务开源项目 cta 正式通过和开启基金会孵化期项目的全票通过。 cta 开源四年来主用于解决分布式事务问题,对于市面上的主流数据库, trc 框架都做了广泛支持,并且被许多第三方社区做了主动和被动集成。该项目有许多特性,提供支持事务模式 的混用,提供多语言 s、 d、 k 支持,支持了多种服务要用框架支持基于多种关系数据库,满足不同誉为场景下的集群高可用需求。 set 的今天离不开所有参与代码贡献的人们。欢迎 q, 有在评论区留下你的看法。