面试官问你分布式事务用过没有?你回答用的 cata, 问你 cata 用的哪一种模式?你吱吱呜呜说默认的,问你默认的又是什么模式?还有什么其他的模式?那每一种模式的原理又是什么?在什么场景去用?我估计百分之九十的程序员都不知道。那我三分钟给你介绍一下 cata 的 四种模式。第一种 a t 模式,那它呢,就是默认的,也是最常用的, 开发成本最低,只需要加个注解就完事了。原理呢?是两阶段提交,在第一个阶段,呃,各分支事务,它会执行 circle, 并且提交 c 塔, 它会同步的去记录安都 log, 也就是将你数据修改之前的快照去记下来。然后在第二阶段呢,所有分支如果成功就删除掉安都 log, 如果有一个失败啊,就用安都 log 之前存的数据,自动的去回滚到原始的状态。那在第二个阶段,它会上一个函所 防止在回滚的时候呢,其他的数据会进行篡改,当然这个锁的时间基本上是毫秒级别的,所以对性能呢,也不会造成太大的一个影响。所以如果你在不知道的情况下,你就回答,我们项目用的就是 c 塔的默认模式,其实也没有太大的问题,因为它基本上可以 覆盖到百分之九十的场景。那第二个模式呢,是 t c c, 它是用来手动控制事务的。三阶段的逻辑,在踹阶段,它会检查并且预留资源,比如说我们一个下单的场景,我会先冻结库存, 而不是直接去扣紧库存,然后在 come from 确认阶段呢,没有问题之后,再进行真正的扣紧库存。那么如果出现了问题,会通过 cancel 阶段 进行释放资源,比如说把之前冻结的库存啊给它加回来,那性能来说的话, a t 模式更高,因为整个过程它是无锁的,但是呢,需要你自己去实现。三个阶段的代码逻辑 成本呢,会更高。那第三种模式呢,叫做 saga, 它和传统的事物其实差别非常大,我们通常说它是用来处理长事物的,但其实呢,并不是去处理一个很长的事物,而是一个 查业务流程。举个例子,比如说,呃,寄快递,我们整个流程呢,会有下单、取件、运输、派送,那每一步啊,都可以分成三个的短事务,比如说在运输出现了问题, 那就依次的取消派送,退回运输、退款,一步一步的去做反向的补偿,那其实你会发现这完全就是业务流程层面的补偿,它不是一次数据库的 a, c, i d, 而是一次业务流程的 a, c, i d, 甚至你都可以把它看作是状态机,指定每一种状态的流程,当业务到了某一个状态,它的下一个状态的整个处理过程。 那第四种模式呢,是 x a, 它是严格的强抑制性啊,它也是两阶段的,在准备阶段呢,所有的分支去执行 circle, 但是注意它不会提交事务,那在事务没有提交的情况下,通常会由数据库自带的事务隔离级别来决定数据的阻 堵塞情况,所以他肯定是会影响病发能力的,直到提交阶段才会通知每一个分支进行事务的提交或者回馈,所以这种性能是比较差的,适合对一致性要求极高,病发量要求不高的场景, 比如一些金融的核心业务,你像银行的转账啊,所以这四种模式啊,大家可以记住一个口令,零清入 高病房选 a t, 它基本覆盖百分之九十的场景,它也是默认的,要性能还要定制就可以选 t c c 长流程需要容错选 java 强一致低病房选 x a。 所以 下次面试官再问你,你的项目用的是 c 塔的哪一种模式,记得结合场景去回答。那关于 java 更多的高频面试题,我已经整合进了一百万次的面试资料当中,如果大家需要的话,可以自行领取。好,同志们,大家好,上一小节我们讲了 c 塔 a t 模式的工作流程, 对吧?啊,这里啊啊,老师留一个问题来看,我们来看一下,就如问题啊,就如何知道调用呢?是同一个分布式事务,哎,对吧,就我们当前的这个下单的这个需求,你使用 c 来进模式的话,你怎么知道它是同一个分布式事务啊? 啊,其实老师讲过是不是,对吧?关键是吧,就是我们会有这么一个全居事务,有叉 id, 查询事务时候拿到的一个从 tc 拿到一个叉 id, 然后我们微服调用期间,我们怎么样要往这个叉 id? 会往我们的下游的微服库存服务啊,账户服务去传递,然后他去注册分支事务的时候,这个分支事务信息里面也会有这么一个叉 id, 是 不是 啊,就是这个点啊,就是大家要清楚的啊,就是会有这么一个全职事务啊,啊,微服间的话会传递啊, 这样一来的话,你就能够区分了啊,它的调用是同一个分布事物是不是?好,那接下来的话我们就去把这个环境搭起来,我们去演示一下,好吧。啊?搭起的话会稍微复杂点,所以大家一定要理解这三个概念啊,就是 tc 是 我们的事物协调者,它是相当是我们的一个服务端,是不是, 对吧?我们有个服务端啊,有这么一个 tc 这么一个服务,那我们不说啊,不说啊啊? 嗯,来我们就不说啊,首先我们要注意这个版本啊,注意版本的话我们是 sata 二点零零啊,这里 是因为当前最新的这个 smart 二零八版本,它整合的是这个二点零的版本啊,但是二点零版本呢?它可能会因为是比较新嘛,很新啊,会有一些那个 bug 啊。生产环境的话,到现在啊,你最好还不是不要上那个最新的版本啊,到时候你可以调一下,调一下版本啊,上生产的话,因为他这个最新版本还是有很多的一些问题的啊,我们等会演示过程中会发现啊。 好,然后下载的话,我们直接下载的话,就是他的一个下载地址啊,然后这里面有很多版本啊, 他的逆时版本都可以在这去下二点几啊,二点零的是吧?然后是最新的还有一点几,一点八,一点七,嗯,好,这是他的一些版本啊,我们都可以把直接下载二点零把它下载下来,下载下来的话,然后官方文档的话,这块也有一个新手部署指南 啊,新手的一个部署指南,这指南的话啊,下下来我们先看一下,好吧。啊,我们去把它下载了,嗯, 下载 c 它我我直接把它下好了啊,下一下来的话,我们可以看一下目录啊,它这边有病康病的话就脚本嘛, config 就是 它的配置嘛,是不是 啊?然后除了它这专门有这么一个目录比较重要啊?这是这这一代包嘛,有个注意啊,那个 set 啊, script 啊, script 这里面有什么有 config center 啊,这是配置中心相关的相关的一些那个配置, 然后是那个 server 啊,这个比较我们会用到的啊,讲一下啊, server 的 话里面有比如 db, db 数据库啊,这有与涉及到数据库相关的一些配置,它都会在这个资料包下面啊,就是大家了解一下啊,然后它其实还有个客户端的啊,客户端的一个配置的话啊, 就是你直接可以去它官方的代码去看找到啊,它下载下来的这个没有啊,没有,它只有 server 啊,然后这一块的话,它的这个讲的就是怎么没有,不太清晰啊,所以这块的话,你你们还是按照老师的 步骤啊,跟着老师的步骤去配好吧啊,这一块的话,然后他还有一些参数啊,有些参数的含义的话,就是很多参数啊,比如客户端还有服务端啊,还有公共部分的一些参数,这些参数的话啊,就是我配置期间 不重要的参数,我就不会去讲解了啊啊,然后你们想知道的话直接在这查这份文档,这份文档的话很多这个参数的话,他都会告诉你是是干嘛了,好吧啊,我们去配的时候我们只只啊,我就只讲重点要改了参数好,其他参数我就不会去略过了啊 啊,然后啊,我们现在要把这个 tc 搭起来,是吧?把 c 塔这个 c 二 c 二单啊,把它搭起来,搭起来,我们就首先啊,我们第一步啊,就是啊,要先要去了解它啊,你不了解它,后面就是你那么配,你不理解为什么就作为 t 三单的话, tc 单的话,结合我们的来结合我们这张图 下单任务任务图,我们会发现无论你是开启全句事务啊,我这边要存储全事务,还是说啊,你去怎么样?你去那个微,我们微服去注册一个分支事务,我们这边也要去存储分支事务信息,这边是要存数据的,是不是? tc 他 要存数据,他存数据的话他接一个存储组件嘛? 是不是你可以存文件,你也可以存啊,存数据库对不对?那这里面啊,我们就先了解它的存储的模式,是我们是可以自行去选择它的存储模式的,所以啊,我们要先了解就是全句式或分支式或信息存在哪啊? 啊,然后啊, set 一 一点几的时候,它支持这三种模式,一种是 file, file 就是 文件嘛,它会全句全句绘化,会存在我们的啊,存在我们的一个内存里面,然后并把它持久化到一个文件, 但是这种文件大家知道我单机读的吗?你除非是分用的分布式文件系统,否则的话你就什么单机的对不对?单机的话只是单机不说,我们一般生产环境不考虑它 啊。然后 d b, 欸,是高可用模式啊, d b 的 话啊,就是我们多个节点都可以去访问 d b, 是 不是它就可以可以那个不完全高可用的啊?然后绘画,绘画通过 d b 共享,但是这种呢 d b 大家知道它的性能稍微会差一点是吧?啊,然后它支持 register 的 话啊,它的性能就比较高,但是 register 的 话有可能会丢失,那个 那个事务性会丢失,对不对?对吧?所以一般啊,如果你的那个对性能要求不是非常高的话啊,一般的话啊,就是 at 模式,基本上满足你的业务需求的话,这种一般它的性能不是要求特别高的话,你可以选择什么?选择我们的 db 模式 以稳定啊,具有稳定性去考虑的话, db 会更好一点,所以这里面啊,就是啊,我如,而且也方便我不要不再去引入一个 register。 是 不是直接啊,我们 现成的那个数据库啊,我们最终啊选择使用那个 d b 的 模式好吧。啊,然后啊,还有一点啊,就是 theta 二点零的这个版本呢,注意啊, 它新引入了一个 ref 模式,但 ref 的 算法呢? ref 啊,就是我们的那个一致性的算法嘛,强一致性算法是不是利用 ref 啊,它可以实现多个 tc 之间的数据的同步啊,矩阵的数据同步,但这种模式的话,现在还不是很成熟 啊,还有理想的方案就可以不用考虑啊,就你们想了解的话,想了解那个 t 那 个 sit 的 ref 模式的话啊,你们可以先去可以看一下这篇文章啊,这篇文章它这面会有详细的那个,呃,对 ref 的 一个介绍,但现在还不是很稳定啊。啊, 对这个啊,这个他这个文章还是比较具体的啊,就是你如果知道这个 reaper 算法的话,可以去看一下这个文章啊。好,他为什么会要考虑啊?这个 reaper 还是想要进一步的去提升我们那个啊, cta 的 一个性能, 因为毕竟存内存里面的话,它的性能还是更好一些,是不是?但是你局群的话啊,你的就会有一致性的问题,一致性的问题的话,你这是你存 db 的 话,它有它还是性能会受影响,即便是 res, 它性能也会受影响,对,它还有丢失的风险,但你如果存在它自己内存的话啊,这种话你就要保证什么内存的一个又是一致性,是不是 啊?就用到一个一致性的算法啊?啊,所以啊啊,老师给他试过啊,就是,所以最终啊选择还是 db 的 方案。 那 d b 的 话啊,它的脚本的话,它的脚本呢?在 server, 它的脚本在 cata 的 server server 这里面,就是在我们的这个 mycircle 啊, mycircle 那 个这里面,这个文件里面啊,我们可以去看一下啊, 看一下它的脚本啊,就是它这面有个全句事物信息,比如有我们的叉 id, 是 不是,对吧?我们有我们的全句事物信息,你看注意看,对吧? 然后你要有一个啊,我们的那个事物的名字等等啊啊,开启事物的时间事,全句事物信息,然后还有个什么分支表,分支事物这里面会存我们分支事物相关信息,是不是啊?然后最后有个什么有个全句锁啊,全句锁,哎,这是考虑到什么?这是因为有可能你操作这个啊, 购买这个商品的时候,其他其他人也会购买嘛,他要考虑什么?考虑我们的一个病发,病发性是不是要实现一个隔离啊,隔离他这边用的一个全据锁这块的话,我们就不在这讲了啊,我们快速体验嘛,我们的后面会在讲 cata 的 时候,这块啊,全据锁啊这些啊,包括那个前置相机,后视镜,我们都包 底层,更深层的原理原码我们都会在后面课程中啊,会散去讲解,这里大家啊先初步了解就可以。好,然后啊,就是这个存储单我们知道了是不是对不对?然后啊,然后也要思考的一个问题,就是我们的 r m 和 t m m 它怎么找我们的 tc 服务啊? 因为因为他都得和 tf 通信吗?是不是就我们下单的时候,你看注意我,我的那个 t m, 我 开启全息输入,我要去从 tc 去获取这个差的啊,是不是我要去通信,我去找啊,那你 tc 部署之后我怎么去找?哎, 如果 tc 是 多个节点部署的话,我是不是又是一个问你一个服务发现的问题啊?对不对?他本身你看啊,本身就是可以作为一个微服务的部署的,是不是 tc, 其实这个时候我们其实可以考虑了吗?啊 啊,我们可以把 tc 服务注册到 nex 注册注册中心,是不是然后 r m 和和 tc 之间就可以通过什么通过 nex 注册中心实现什么 tc 的 服务的发现,对吧?我们可以怎么这样?我们我们这个 tc 局群啊, tc 局群我们可以怎么样注册到我们的 nex 的 注册中心,是不是然后他们去共享我们的事务信息啊?然后我们微服务器呢?整合了 r m t m 之后,我们怎么样?我们同样的我们怎么样? 只需要从我们的 nexus, 我 们拉取到 tc 的 数, tc 的 服务列表,然后我们去发起调用,是不是就可以了, 对不对?所以这个里面我们 tc 端其实也可以怎么样把这个服务注册到我们的 nexus 注册中心, 对不对啊?这是这个点啊,然后就注意啊,就是你的 tc, 你 的 c 的, 它是可以独立部署的嘛?它使用注册中心可以和我们的订单服务库存服务的注册中心可以怎么样?可以是无关的,你可以搞两个注册中心, 对不对?哎,你也可以共用一个,对不对?当然一,一般共用的话,我们可以可以怎么样?你可以建一个 cata 的 秘密空间,把我们的 cata 服务和我们的 cata 和我们的业务的微服务啊,我们把它分离啊,分开来,因为你的 cata 这个环境有可能怎么样? 我有多个微服务项目都可以去使用它,是不是?这种情况下的话,我们完全怎么样?完全,我们可以去去使用它,是不是?这种情况下的话,我们完全怎么样?完全。我们可以去在这秘密空间去建一个 cata 的, 创建一个 cata 的 秘密空间。对,创建之后我们怎么我们把服务注部署在这个 cata 这边,包括我们的配置都都放在我们的 cata 这个秘密空间下面,是可以的嘛?对不对?好, 这是啊,这一个点啊,就是你先要去了解啊,了解它怎么去找到的啊?对,即然啊,即然我们服务注册,注册到,注册到 nexus, 同样的,我们的这个配置信息是不是也可以交给我们的那个 nexus 去管理啊? 它作为配中心对不对?好,那最终的话我们部署的方案是不是就成型了?就数据库这这段,存储这段啊?存储这段我们选择 d b 啊,然后就是我们还可以怎么选择 nexus 作为我们注册中心和配中心?好,这是最终的我们选择的一个部署的方案 啊,这个方案清楚之后,我们接下来就可以什么去把这个 theta 这个环境,七次单的环境把它搭起来了。好,前置环境的准备,注意啊,第一个就是你的 d b 要准备好啊,准备好,就是准备好我们 theta 的 一个数据库啊, theta 数据库, 然后要准备好 lab 环境啊,我们已经准备好了,是不是已经准备好了啊?然后 d b 的 话就是你要建好,比如我就建了这么一个 set, 二点零这个表啊,这几张表我导进来了啊,都导进来了啊,就是就是,刚刚这个 set 文件是不是把它导进来了啊? 好,这个是准备了,是不是?好,然后,哎,就是我们要怎么样?现在我数据库这个存储已经配好了,是不是?那我就开始怎么样,我要去怎么样?我要去配置我们的 注册中心的啊? set, 那 比如我们 set 服务,我们现在怎么样?我们现在起的就是把 set 服务把它下载下来了,是不是?然后啊,我们启动它之前在脚本,这是启动脚本是不是?启动之前我们先要配它,是不是配置它,我们找到 config 下面它就会有它的那个配置的脚本,比如, 嗯,你扫一眼嘛,看到一个 openkey 点 yum, 你 就知道这肯定是它的配置文件是不是?那配置文件的话,注意啊, 这配置文件我们就可以去配是不是?那关键大家去配哪里啊?注意看看档口啊,档口有没有冲突,如果有冲突改一下档口,没冲突,不用管他啊,七零九零啊,他是七零九幺啊,七零九幺,档口占用啊,然后啊, c 塔啊,这控制台,他的一个用户密码是不是 c 塔, c 塔啊啊,然后 注意啊,关键是这个配置,这 set 里面有个什么,有个 config, 有 个 registry, 有 这两个配置,然后 store 存储这块不用动它,不用管它,因为这个存储这个配置我们把它我们会交给配中心管理, 所以这面我们就 d b 选择哪一个,哪一种存储方式,我们不用不用动它了啊,不用管它了,好专,关键看这两个啊,就是 paycom, 就是 pay 中心嘛。对,我现在看注册中心,我要把它注册,它可以支持 lexus, eureka 很多啊, reg 啊, regis 啊, zk 啊,这些都支持,但我们现在什么选择类型,我们就选择 lexus 就 可以了,是不是 好?选择 x, 然后我们要把它注册嘛,啊,作为一个服务注册啊,它这个服务作为一个是服务的名字,指定一个名字啊,叫 cata cire, 然后我们客户客户端,我们微服去整合的时候,我们去找这个 tc 服务的时候,我们就知道是找这个 cata cire, 是 吧?找这个微服就可以了。好,然后指定一个我们的 注册中心的地址啊,这指定我们注册中心地址,八八四八是吧?档口啊,然后注意啊,我们看密空间, cata 指定 cire 密空间, 对吧?把它注册到 cata 应用空间下面。好,然后呢?注意啊,它的一个给它定义了一个组的名字啊,就是分了一个组,是吧? cata group 啊,这是,这是与 cata 的 啊,这,这所有 cata 服务注册这个组,下面,好,然后注意啊,关键有个什么 cluster, 非常重要的 cluster 局群 default, 这个局群注册上去它默认啊,每个微付默认它默认它就是那个,它会有个名字的啊,它有个名字就叫 default, 是 不是包括我们之前的啊?你看我们之前注册的那种啊,订单服务啊这些,你注册之后, 比如说两个啊,它它都有个局群名字都叫默认叫 default 啊,就指定指定给它指定个名字,然后我们就我们微付端,到时候我们 r m t m 去找 t c 的 时候,我们可以通过这个这个那个局群的名字找到这个局群,是不是? 好啊?啊,这是这块儿啊,就这块儿啊,就证明有这几个配置要注意一下啊,就是就是,先啊,第一步就是你要将什么将我们这配置,将 c c 网注册 nexus 修改这个配置啊,就 这个 register 下面去配置我们的 type nexus, 然后指定是我们注册中心相关的一些配置好,配好,配好,然后一定要注意啊,这个 class 这个配置非常重要啊,默认代表 tc 群,对 t m r 们就要通过这个矩阵名字啊 default 去找了 tc, 那 它是怎么去找到 tc 的 嘞?这里面啊,这里面就是 它会有一个配置啊,我们会在配置中心,配置中心时候会去讲啊,有个事务分组,你用事务分组去找到它的啊,然后这里面一定要注意啊, 就是,嗯,你要注意啊,就是你现在是指定的,你要记住啊,是 cta group, 是 cta group 是 吧?那么 space 是 cta, 你 后面你去配 rmtm 的 时候,你这个要一样,不然你就找不到这个 server 服务。这是很多人啊,遇到 啊,使用 cta 的 时候遇到的最大的问题,就找不到 tc 服务啊,一启动报错维护,一启动报错就找不到 tc 啊,就是要注意啊,就很所以这个地方注意一下啊,排查问题时候我们就看看这个地方啊。好, 然后啊,我们注册中心啊,就是你如果配了这个东西啊,就配好了,我提前已经配好了,是吧,我就不去动他了啊,配好了是吧?好,然后 看啊,我们的模式 d b 已经配好了,数据库已经有了,是不是?好,然后注册中心也配好了,启动话会注册到我们的注册中心,配中心呢?我们还不配,是不是?那我们把配中心 弄一下,配中心好, nexus 配中心,它会有很多的一些属性,我们要怎么样?我们要去配啊,我们配到哪嘞?那我们也去指定一下,比如我们指定配中心也是 nexus, 是 不是 nexus, 然后什么指定?我们配中心地址直接直接看,这也是一样的啊,来,直接看啊,我们配置一个配中心啊, 配容芯的地址是不是,然后它的命名空间啊,然后它 group, 注意这个 group 名字啊,是 set group, set group, 然后 data id 是 server 啊, set server 点 yam 啊意,意思就是说我们会在我们的这个命名空间上面, 在 linux 的 我们的这个配置中心的这个服务列表里面,在这个 set 命令框下面,我们会有一个什么 set server 的 properties 啊,就 data id 名字是不是有这么一个配置文件啊?有这么一个配置文件啊,指定的啊,指定的啊。好, 就是这个点啊,来来啊,我这是要是 properties 啊,来改一下, 对吧?要,你要名字要一致啊,你这边是 purpose 这边啊,它也要是 purpose 啊。好, 然后我们进去看一下啊,来,进来,进来看一下,这面就这里面就是它相关的配置嘛,然后一定要注意啊,就你默认创建的注意啊, 你如果创建了默认主页,它是 default group 啊, default group, 你 要记得你要什么,你是 set group, 你 要一一对应啊,如果你那边是 default group, 你 要把它改成 default group, 一 一对应,不然你找不到啊,你到时候你拿不到这个配置是不是?好,然后进来啊,这里面就会有它相关的一些配置。 这个配置信息哪里来啊?这配置很多,是不是哪里来的啊?哪里来的啊?在这个地方啊?啊,我这面都在那屏幕给大家详细的说了啊,将我们的 c c 位的配置上传到配置中心。哪里来的?它是在这个目录下面 set script config center config test, 就 在我们的那,在我们的这个包下面啊,看脚本,这里面配中心是吧?配中心下面有这么一个,你看有这么一个配置,然后啊,你把它打开 啊,你会在这里面看到很多配置,看到很多配置,是吧?啊,然后把它上传啊,把它上传就可以了,但这里面有些配置你不要了,可以把它干掉,比如啊,就是比如我们往下翻的话啊,啊, 比如你看它这里面啊,这里面告诉你啊,如果你是用的注册中心下面这个配置给忽略这三个可以干掉,是不是?好,然后啊,你比如说你,你这是,我是 db 的, 是不是 db, 我 就使用 db 的 话,那,那我, 那我 fire 的 配置,存储配置,我可以把它干掉,对吧?然后你像 release 这个配置,还有还有像什么我们的 raft 这个配置,我都可以把它干掉啊,干掉就可以精简,这是我最终的一个精简版本啊,就是最终我给大家 准备了一个精简版本啊,精简版本就是我最终的这个效果啊,最终效果这个也是给了给了大家啊,就是有一个完整版的啊,最终会有一个完整版的一个配置啊,全部给大家啊,然后这里面我们要改几个东西,这个配置还是比较复杂,是吧? 这面有很多的属性,大家可能不知道,不知道的话啊,老师之间在这里面给他提供了这么一个,哎,是吧?提供了,提供这么一个配置参考官网的参考,是吧?有个参数啊,这是参数,大家自行去了解。好吧,感兴趣了,老师,这里面就只讲重要的核心的。 好吧,我们需要修改的啊,那我们就去看一下啊,那这里面啊,比如说我们,我们是选择的是 db 的 存储模式,所以我们改什么?我们要改那个 my secret 或连接这块,是不是?那我们就去找到这个配置,那我们就找到这个配置,那我们改到 db 这块了啊,这是传输层,我们不用去管 db 这块儿来找到找到存储这块儿啊, store 是 吧?模式要改成什么?改成 db, 改成 db 好, 然后,哎,还有它有好几张表嘛,啊, lock 表啊,然后筛选规划表都要改成什么都要把它改成 db 啊,改成 db, 好, 然后,哎, 好,然后啊,我们这里面注意啊,你如果使用的啊,它使用的是 my sql, 是 八零几 啊,你或者是 mac 有 这五点七,你用上面的是吧?你用八点几的话,你要把驱动改一下驱动改一下,然后你要改一下它的连接方式,它连接方式它是有区别的,对吧?啊,这是这个点啊, j d b c 我 们要改一下,然后指定它的用户密码啊,其他的默认配置你不用动它啊。啊,这里这个地方要注意一下啊,注意一下 啊,因为因为早期版本的话,早期版本的话可能这块儿啊,它不支,这块儿的话它不支持 micro 八啊,你要去改一下啊,官方它这里面有个说明嘛。啊,你可以去看一下啊,官方的啊,常见问题的话,这里面会会有这个说明说 tc 如何使用 micro 八 啊。你要首先你要把它这个驱动名字,这个名字 driver class, 那 么改一下,然后在 neil 帮下面添加了它这块帮大家处理了,我们给来看一下啊 帮大家处理了,你看它这面 label 包下面就它依赖嘛,这面有个 g d b c, 是 不是它两种啊?两种包都都在都放在里面了,已经放帮我们放好了, 你只要怎么样?你只要啊,去按它的要求去把这个驱动改一下,把这个连接的这个元参数啊,配上参数不一样,稍微有点不一样,把它改一下就可以了。好,这是这是我们的这一款啊,这是我们的数据库这块 db 的 存储模式修改好,然后,哎,然后注意啊,就是一定要配置一个 事务,配置一个事务分组,这个事务分组非常重要,非常非常重要啊,你要找这个 t c 局, t c 的是 default 局群,怎么去找?怎么去找, 就是与这个配置有关了啊,这个配置是什么?就是我们的 service v group mapping 点 default, ts group default 啊,这就是事务分组名字,就是这是他默认的,你给自己取个名字,比如我是下单服务,我可以来个那个订单 create order test group, 是 吧?可以自己创建一个事务分组啊, 这个题可以灵活,但是你的微服呢?它需要是需要去配的,明白吗?啊?然后这后面就有我们局群的名字, 我们我们局群名字,这是事务分组啊,就是你可以把你以为什么呀?就是 set 的 一个逻辑上的一个隔离,隔离这种方式 啊,就是局群它是用的什么?你比如说 tc, 它是用 default 的, 局群 default, 我 们指定是 default, 是 不是?然后啊,你这后面就要跟你 tc 局群的名字,明白吗? 明白吗?啊?前面呢,就是你去配了,你去配的这个值是变化了,这个是在我们的微服端,我们就要去配了,要去配这么一个值,这个值是可以自定义的,但是你一定要通过这个值,你要对应这个值,你能找到 default 就 可以了 啊,这是这个点啊,很多人就找不到 tc 的 话,就是这个配置没有处理好。这个配置很重要啊,就是事务分组如何找到后端的 cata 服务,这也在官方,他也在这专门搞了一个专题看啊,事务分组特别强调我们这个事务分组 啊,首先应用程序那段啊,它会专门配一个什么叫 cata ts, service group, 有 这么一个配置,这个配置你就要指定什么,就指定指定我们刚刚的, 哎,来看这个名字啊, service 点 group mapping 的 就这个名字,是不是?对,指定这个名字通过这个名字可以怎么样?它拼装好之后看,拼装好之后它就等于我们的局群名字,等于我们的 default, 是 不是通过这会找到我们 default, 否则找不到啊? 通过它拼好之后,拼装好之后,它从我们的注册中心就可以拉到。什么?拉到我们所谓 default tc 群, tc, tc, tc, tc 服务列表,然后怎么样 啊?拿到我们的 tc 列表,然后就可以掉了,是不是?好,这是这个点啊,就很重要,好吧,这地方一定要重视。好吧,好,就是要这么配一下啊,配一下,所以在我们的配中心里面,我们的这个地方我们要改一下,是不是?那你你,你如果用它默认了,你不用动,对吧?默认的不用动,你等下配 在我们微付那,那配十五分组的时候,你要指念这个名字要变,你如果那边变了你这名字,你怎么样?你你,你要改一下,是不是,对吧?啊?他可以治多个啊,但是你都要去改,你都要让他找到,懂吗?你如果每个微付有个十五分组的话,那你这就要配置,可以配置多条记录,他不冲突吗? 对,每个微付一个自己的一个十五分组的名字,但是一定要都要指,指向是我们 tc 局训的名字,好吧,好,这是这个点啊, 我说的比较多啊,因为比较重要。好,然后,哎,就是在我们 next 编辑就新建就,就建了这么一个 set serve purpose, 是 不是然后编辑上修改之后了啊,就这完整的完整内容啊,就把它放上去就可以了啊。 这面就两点注意了,第一点就是什么?一定是在 set 密密空间下建的是不是啊?然后啊,是和我们的那个 application 一 样,里面的这个 config 配置能对得上啊?是 set group, 是 set 下面的啊,密密空间下面的句型名字是 default 能对应上啊,特别注意啊,就是 server 的 group 是 不是 set group 好,对吧?一定要对应啊,你改了,你改了,那你改了,那这边呢?就是你比如说你把 group group 改了,那 group 要对应,好吧?好,这块如果没问题的话, 那我们就可以怎么样?我们可以直接在 windows 下面,我们直接可以启动这个脚本了啊,直接启动这个脚本来,我们去启动啊, b 下面双击就可以启动了,来,直接双击启动。 哎,我们的这配置没有保存是吧?啊,不是这个 yam 啊, yam 是 保存,保存一下啊,等一下,我保存一下啊,保存一下,我们再重新启动一下 set 三二,这是 nexus, 是 不是好 好 set, 是 不是 set 我 们可以看到它启动了啊?好,我们的 server 单是不是已经启动了?启动了啊,那接下来啊,我们去看一下啊,来,我们趁热打铁啊,我们去看一下我们微服端要怎么去配 啊?这里面就一步一步来啊,微服端我们要回顾下我们业务场景,我们的目的不能忘,是不是我们是用户下单,是订单服务调我们的库存服务去扣奖库存 啊?第二个我们账户服务去扣减我们账户余额,是不是?然后事务发起者是我们订单服务,事务参与者有我们的库存服务,还有账户服务,这个要分清, 分清之后我们就可以怎么去配啊,比如我们订单服务怎么去整合啊?事务发起者怎么整合 c 塔?事务发起者呢?肯定是需要什么需要我们整合我们 tc 的, 是不是啊?怎么去做的啊?看啊,首先第一步引入我们 c 塔依赖啊,那引进来我们就一步操作啊,引入 c 塔依赖,这是阿里巴巴杠 c 塔, 哎,找到我们的订单服务,好,我们订单服务,这是我们的订单服务,是吧?好,哎, 订单服务我们引进来,引入 seta 的 依赖,好,我们来去订单服务导入一下, 依赖导进来,是不是?好,然后,哎,然后注意啊。第二步 就是订单对应的数据库要添加一个 auto log 表,仅 at 模式,它需要这个 auto log 就 回滚。日制表就要有这么一张表,我们我们之前导数据库的时候就已经添加进来了,对吧?所以这步我们就省了啊, 来,就这张表,这张表里面就比如一个叉 id 啊,哎,分之十五的 id, 然后还有个回滚,对吧?哪个分值能够回滚?它的数据其实存在这啊,存在这里面的,好吧,这是点啊,大家了解一下。好,然后, 然后啊,就是,呃,是这样的啊,就是我们的订单服务啊,到,哦,不,你看你一样么重要。添加 c 塔的配置是吧?添加 c 塔的配置,注意啊,那添加 c 塔的配置 在我们这里面是不是去添加它的配置?添加配置,我们要把 c 塔的配置把它添加进来是吧?添加进来啊,注意啊啊,需要什么?需要在 network 空间创建一个 c 塔的名空间,用于和我们的业务微附近隔离啊。 啊,就是已经创建好了,是不是对吧?然后注意啊,请确保 client 和 server 的 注册中心的配置和注册中心的配置 name space group 要一致,不然的话你的微服务到时候 t m r m 找不到 tc 是 不是好,然后的话这块配置的话配置这它的配置,你看这块配置, 把它复过来,复制过来啊,哎哎,好,复制过来,我们来看一下啊,看一下。它是这样的啊,它是一个什么?它是一个 cata 的 一个配置,是不是啊? cata 一个配啊,我考到后面一点,考到后面去, 因为这个 data 它是 spring 下面的嘛,是吧。这 cata 是 顶格的啊, 好 set 啊, set 来,注意看啊,这里面啊,这里面它就定义了我们的注册中心和我们的配中心地址,你要和我们这个对应的注册中心配中心地址对应是不是? 对,因为你也是为了去找什么?你是为了去找我们的 tc 服务的,那你要去拉取 tc 服务的它的什么?它的服,它的配置。 那比如说你的配置中心,你要指定是不是你要拉到了一个配置啊,拉了配置的话你要怎么?你要同样你要指 data id 是 是 cata server properties, 对 不对啊?同样的注册中心的话你要找到,找到 tc 服务的话, tc 服务的话你是不是也要怎么样?指定是 microsoft, 然后 cata server, 然后指定它注中注册中心的地址,然后怎么样? name space 也是 cata 也是 cata group 啊,这个要一样的啊,这个保持一致,不然你找不到。对,还有最关键的就是什么最关键的时候它是根据规则去拼的。 你的这个微幅段要有个事务分总,是不是要指进什么 test service group, 要指进什么 default test group 要和这个一样, 要和这个东西一样,那么要和这里面这个名字一样。你如果你的这边改了啊,比如你加个叉叉,是吧?你这边就要怎么样也要加个叉叉,明白吗?好,那我这边我就对明不明白啊,这些就保证一样啊, 好,这是这是这个点啊,一定要注意了,好,了解这些,了解这些,这没问题啊,就是你把它配进来啊,就是因为我是呢,我是那个 play 的 配中心,像这个配置的话, cata 的 配置的话,我就可以怎么样单独的优化了。配中心,是不是我可以在怎么在我们 nexus 配中心里面,我可以去建一个什么 cata client 的 一个配置,我可以把它怎么样导进来,对吧?把这个配置导进去啊,导进去,我在微服里面我只要去引引,引一个我们 cata client 的 配置是不是就可以了? 来,我直接,我可以不用不用,不用这么去拍了啊,因为这是个公共配置吗?我三个微服我都要用这个配置,我完全可以交给配中配中心去管理,是不是,对吧?啊?我就直接引进来啊,引进来,然后我只需要在我的对应的啊,我们的 nacros, 我 们的配中心里面啊,注意啊,这个我们是用了公共的,公共的民空间,我们这个呢配置使用公共民空间,是不是在这个下面配置一个什么 set client 客户端的一个配置,来,我们看一下,这象形是把我们的配置直接 复制过来了,对不对?好,这样一来我们配置就没问题了,是不是?好,没问题啊,那我们就怎么样,我们就去把它起起来啊,这个配置配完了,是不是啊?我们来检查一下啊,检查一下,这个是没问题的,是不是没问题啊?没问题。好,这是到这一步啊,是没问题的, 这三步就把我们的 set 完全接住了,是呗?然后定单符它还有个特点,它是作为事物的发起者呀,你怎么做开启全句事物,哎,这里面它是干嘛在我们全句事物发起者的方法下单方法上面添加一个什么?添加一个 global transaction 的 事物的一个注解,添加这么一个东西。来, 在我们的这个方法上面来去添加啊,我们的这个注解,全句事物的注解,这样一来就可以搞定了啊, 这个开启啊,添加我们全数据,注意,然后我们呢?啊,要回滚的,如果遇到异常的话,我们要回滚,是不是?好去 create 创建订单啊,这样一来的话,注意啊,这样一来我们数据开启了,我们的全据事物啊,对不对?整个就开启了,全事物就搞定了呀? 啊,这是因为他做事物发起的需要开全事物,所以我们需要引出什么格罗波存在性注解啊,然,然后我们微服的话,每个其他的微服的话,我们只要怎么他用本地事物就可以啊,好,这是这就是这个特点啊,他做事物发展,那事物参与者嘞?我们的库存服务还有账户服务,他做事物参与者的话, 只要什么,你前面三步是一样的啊,你要接入 cata 是 不是?接入 cata 是 三步啊,引入依赖啊,然后业务库的话要增加一个 onload 表啊,然后就是我们要在样板里面配置 cata 啊,这是这三步啊,这三步。然后啊,最后就是每个自己的这个减库存的方法,要加上一个 本地事物的注解啊, spring 事物注解就可以了啊。啊,这个没问题,这个我们都加了,是吧?我们把前三步实现一下啊,比如第一步引依赖啊,我们都去引一下啊,啊,我们就同步去引呗,我们的,我们的库存服务,我们也要怎么样啊?去加一个啊,加一个 啊,库存服务我们刷一下进来啊,然后啊,他要在这边去引一个进来,是不是?哎,加我给配中关系管理之后非常方便。直接复制过去是不是就可以啊?是吧,来, 直接引过来是不是就可以啊?来,很方便,对不对?这样一来的话,哎,我们的 set 的 配置是不是又引过来了?好,同样道理啊,我们的那个账户服务也是一样的,是不是先先引依赖啊?引依赖, 哎,依赖啊。第二步的 on the log 表我们是已经建好了,不用管它是不是好,来啊,在这段处理,把我们的这个依赖导进来啊, 我这些小圈圈都没有了啊,然后好导进来,是吧,然后在我们的样里面,对吧,然后我们再引入 c 塔的一个配置,是不是?哎? in c 塔配置我们复制一下啊, 好,引入 c 塔的公共配置好,没问题,是吧?检查没问题啊,然后我们就可以把这三个微服把它骑起来。是不是骑起来啊,我们先去骑起来,来三个微服去骑起来。好, account order 那 个 storage 啊,那我这骑我就关掉一个啊,我们再去骑这三个。来 啊,我订单服务的话,第八个方式起吧,我给大家看一个效果啊,就我们第一阶段呢,他来我给他看一个效果 啊,第八个方式去起一下啊。嗯, 你要检查一下有没有报错,有没有报错,如果没有报错的话啊,如果没有报错的话,应该是没问题不大的啊。 没,应该是没有报错的,正常情况下啊,你跟老师这个思路来应该是没有报错的 啊,好,可以啊,但是如果你选择 reaper 模式啊,它有可能会报错啊,然后你用老师个配置啊,就把无关的配置,特别是 reaper 配置啊,干掉啊,干掉,就是这个服务段干掉,如果留在那里的话啊,它有可能会有影响 啊,也确实有很多 bug, 我 看到那个啊,官方的一宿啊, c 塔二零二零零点零提交了好多 bug。 好,是否参与者是不是也整合了啊?就是库存账户我们也整合了,是不是?好,此时我们这两步我们操作就完成了,是吧?完成了,那我们就去测一下啊,直接看一下啊, 来啊,我们去测,我们去测啊,然后这里面有有几个大家可能会遇到问题啊,我在配置过程中我也遇到了啊,我给大家去讲一下啊。第一个问题,什么就是说有这么一个问题啊,就是说我们什么就是 配置啊,找不到啊,找不到,就是 service 为 group mapping default, 我 刚讲过,是不是对,找不到解决思路 就是无法拿取到这个 default 这个配置啊,就你有可能的,你配置中心没找,没拿取到你配置中心配置就你看一下你有没有配置事务分组啊,是吧?微服下面有没有配置这个事务分组啊?同时怎么样?你的那个 name space group 有 没有对应啊?老师就犯了个错误啊,我的 set server 的 properties 就 没有 用的是默认的分组啊,其实 set 的 分组是不是所以他找不到啊?这是一个思路啊,排的思路啊,就是你要就是找到拿取到这个配置啊,配置啊,然后他会,他拿到配置之后他会就会找到什么,他会找到 service v group mapping default 这个配置,是不是啊?他其实这个配置是必须的啊 啊,然后还有就是有可能服务端他有可能那个 j b c 连接报错啊,对吧?这里面你就怎么样无法检测数据库的配置对不对啊?就是用户密码呀,对不对? 然后你要检查一下 j c b c 的 配置啊,版本呐,这些匹不匹配啊,都要考虑一下啊,这是大家最容易常犯的两个错误,一个是数据库连接这块啊,然后一个就是我们的十五分组这块啊,然后就是那个我们的配置中心 group 啊, name space 啊,这这块啊,没有对应上 啊,这块都解决之后应该是没有问题的。好,然后我们就去测啊,首先我们就就是以下单这个操作,我们去测嘛,下单啊, a t p 啊, no, 八零八零是吧?啊?比如我们来一个 啊,我搞一个正常的,我先把这个库存啊,库存也少了,是不是库存我调大一点啊,只有一个库存是吧?我调调五十个啊啊,库存让他保证库存没问题啊,然后我的账户的话我调个,我搞个三吧,三的话我只能下一次单,下次下单的话他就是余额不够了,是吧?好, 这个也没问题的啊,我这个服务也齐全了,数据库数据也造好了,是不是?好,然后我们来去调一下啊,此时我去调啊,来,你注意啊,我提交 啊,来,我们来看一下。 好,这里面啊,就有了那个 set 二点零整合的啊,它有出现了啊,这么一个 bug 啊 啊,就是 index 你 out 五棒的 for last 零,这是 c 二零零整合之后在那个官方一小里面非常常见的常见的一个 bug 啊啊,这是这是内部的错误啊,它内部的一个错误,你看 啊,等一下,我这这这次遇到了啊,哎,因为我的库存服啊,他扣奖库存啊,扣奖库存,我是开始掉了是吧,然后他报了个异常啊,报了个异常,然后我们的订单这块肯定是失败了是吧? 订单失败了啊,然后他看他是回滚的,正常回滚的是不是?对,所以我们我们的试问也整合进去,但是他因为自身的那个最新版本的这种 bug 啊,他导致他出了问题啊,然后这块了。我去,我现在先去处理一下啊,处理一下再给大家继续啊。好,老师刚把这个问题解决了啊 啊,这是我之前的配置的一个坑啊,就是你直接从我们这里面去考了个配置啊,他会有点问题啊,就是你直接从我们这里面去考的这个配置啊, 可能会有点问题啊,你要把这个注式全部干掉啊,你把不相关的配置还有注式全部干掉,干掉之后啊,就是你可以,你可以用这个有一个转换工具啊,就 to yum com, 你 把它贴进来啊,贴进来,转成 yum 之后,然后再转回来啊,把这所有相关的一些配置它全部给你干掉,干掉之后你再把它贴到我们的这个配置中心 啊,贴到我们的这个 sierra sever 点 purpose, 把它贴过来啊,把它贴过来,然后再发布啊,就可以了。好,然后你这边去 啊,这边啊,对吧?是指进我们的 sierra sever 点 purpose 没问题啊,然后去把我们的这个 sever 服务把它重启,重启之后就可以了啊,这是它的一个坑。 哎呦,这个坑哎,这个坑的话你看啊,一小上面有很多种题啊,你看我你随便搜一下,比如说 in doubt, 你 out 棒的 nice。 你 对好多错误啊,就他一直没有人解决,是不是 没有人解决啊?用了很多办法啊,有的是,有的他说是要降低版本啊,他说啊,最后最后最后解决是什么啊?换了版本就没问题了啊,对吧?其实这里面是他的配置里面就是什么啊,换了版本就没问题了啊,对吧?其实这里面是他的配置里面就是什么啊,换了版本就没问题了啊,对吧?其实这里面是他的配置,里面是什么啊?换了版本就没问题了之后 啊就是把这个配置全部把它干掉啊,把这注式,把这注式全部干掉,还有不相关的配置,特别是像像我们的没用的 ref, 是 不是 ref 相关的配置把它全部干掉啊?干掉, 只保留你需要的一些配置啊,大家直接啊直接就可以。呃,关于这个配置的话你直接用我这个笔记上面的这个配置啊,把它贴的是最完整的啊,把注式全部干掉了啊,然后把它导进来就可以了啊。好,就是关于这款啊,就是不是就有一个坑啊,对吧? 所以 c 塔的话它当前这个版本它还有很多 bug 啊很多 bug 的。 好,那这没问题啊没问题,我刚刚测试下单成功的啊,然后把这个数据啊把它恢复一下啊,比如说恢复为三啊,然后我的这块的话我恢复到五十好吗?好, 来啊恢复我们再测一下啊注意我们去测一下啊刷一下。好,此时我们注意啊我们去提交提交的话啊然后我们来看一下 啊。余额不足是不是余额不足哎,我这边没有没有没有给他添加上吗?啊没有提交啊是吧啊好,现在现在提交了,之前是余额不够,是不是余额不够的话他又是有个坑的啊,那我们再重新提交一下啊, 我们等下来看余额不够的时候啊余额不够的时候他是不是回滚的是不是啊?库存的话你看啊我们库存的话他其实也是回滚的啊啊余额不够的话刚刚是没有来库存还是五十没变是不是我们再重新测啊重新测啊, 好,来啊,我现在提交啊好,提交的话注意看是五十三,扣奖为四十九一了,是不是对吧。啊,我们的 订单是提交成功了是吧?成功这是没问题啊,然后我可以去看一下的日期啊看啊,我们订单的日期啊 啊看一下日期这边啊,这样我们可以看到他是怎么样呢?就是有一个全据事物相关的信息啊,分支事务注册成功啊,是不是啊?然后啊我们的提交,你看我们的这个事务是提交了啊,然后我们的这个这个最终也是提交了的啊, 一个是先是本地事务提交,然后就是我们两千人提交,之前我是不出,之前我出问题余额不够的话,看看它是回滚的,是不是?好,这里面我加上加上几个东西啊,把把这些相关的东西,日制我们都加上啊,我们打印一下它的差 id 啊,我们可以,我们可以把它差 id 打印出来啊,我们这里面都都把它的差 id 打印出来来啊,我们都加上啊, 好打印叉 id 啊,然后我们的账户的服务的话,我们也可以打印一下这个叉 id 啊,就是我们可以看一下它有没有传过去啊?全区是外地啊,有没有传过去啊?都都打印它是吧?好,我们再把这几个服务,我们把它重启一下啊, 那啊把它去重启一下啊,我的订单服务我要以第八个方式去把它启动啊, 那啊 我们把它重启一下啊,然后我们在这里面做一个测试啊,我们在这里面干嘛呢?我们在打个断点啊,注意啊,我们在这验证时候我们打个断点啊,在我们的,比如我们可以在我们这里打个断点,是不是 打个短点啊?我们打短点,我去看一下我的库存有没有扣减,是不是此时此刻啊?我们现在我们是余额是不够的,是不是余额不够啊?只有一啊,他要扣扣扣两块钱肯定是不够的啊,我们去看一下我们等下下单的时候我们的库存有没有扣啊?然后再打个短点,是不是 啊?落在这,好,来啊,注意啊,好,此时我们来看一下我们的库存是多少?库存是,现在是五十,是四十九,是不是四十九啊?然后我们去下个单啊,然后我们账户余额现在是一,好,我们就去验证一下,我们去下单。 好,这里面它有个小问题,这小问题我先通过 pos 问,我去那个测试,好吧。啊,哎,它这面有有个 bug 啊。啊, 好,我下单啊,我去下单。好,我用 postman 去下单啊。 create 创下一个单是不是好扣减?扣减那个一都是一,是吧?好,好, 此时注意啊,注意啊,注意。我现在下单操作是不是我下单,我执行好,下单的话 我落在这是不是?然后我赶紧去检查一下,你看啊,我们现在你会发现怎么样?它库存是扣了的,是不是?好, 库存是扣的,对吧?但是四十八,他就是说他本地是不是提交了?好,我们继续往下执行啊,把单点去掉,我们继续往下执行。好,执行,但是我的肯定啊,我的要回滚嘛?是不是要回滚?好,然后这边他就会有异常,告诉你抛了一个异常。我的什么?我的余额不够,是不是我的余额 不够?这是个业务异常,因为我在这边定义了个业务异常嘛,当我的余额不够的时候,我抛的是个业务异常,对不对?好, 我的库,我,我的库存库,你可以很显然会看到,怎么样?他是回滚的了,是不是他是回滚的了啊?那两阶段啊,他是回滚啊,就是我们第二阶段就第一阶段是本机书提交了,是不是?第二阶段就是我全机书要回滚啊,他回滚了,回滚的话,你看啊, 他的这个四十八会变成什么?四十九,就说明我们的这个分布失误啊,他整体来说是没有问题的,对应我们的我们老师之前讲的这个下单这个流程 啊,我们看的我们这个下单的一个流程啊,当我的账户服务余额不够的时候,我是怎么样? 我是全据事物会抛异常,补货到异常之后通知通知我们的啊,那个全据事物 tc 回滚 tc 的 话,它会去驱动什么?我们的库存服务这个分支,它通知分支回滚, 对不对?由什么?由四十,由我们的四十八又回滚为我们四十九,所以这个整体这个逻辑他是没问题的,我们 c 到整体的是不是?但是你看啊,我这补货的是业务异常啊,业务异常是不是 啊?然后啊,就是你这边给我抛的什么?抛的是个五零零,就是他有问题,他有问题。为什么呢?就是他补货异常之后,他给他抛了一个 round 一 场 啊?这是,这是我们的啊,就是 cata 的 二点零那个 bug 啊,低版本它不会有这个问题。 哎,就是低版本就是又有个 bug 啊,它好 bug 很多啊,所以我将生产环境,大家现在还是先不要用那个 cata 二点零的版本。是否?虽然回回成功了,但是呢,最外层的代码是无法捕获到原始的 business 机上,只能捕获到一个 round time 异常 啊,这原因分析啊,这里面就是给他贴一篇文章啊,贴篇文章他会有什么?抛出一个什么 try to process 的 一个一个异常啊,我们,我们直接,我们直接可以去试一下啊啊, 他的版本啊,大家降,大家降低版本就可以,你现在用这个最新的二零二三的版本有问题,你降到二零二二版本就没问题。就这块的话,这块的话我们就是直接啊, 你直接看我就这一这个地方处理啊,我是怎么样?我是捕获到你这个就是余额不够的 round 它们异常,我是要怎么样?我要返回了是不是?但现在它处理之后帮我抛出是个 round 它们异常,所以我这边什么这边拿到是个五零零,是不是?所以这面又怎么样?你要还要再开启一层 是不是?你再客气一层?来客气一层,我们 excel 不 行啊,我们把这个异常打出来看一下好不好?来,我们把我们把这个地方啊,那直接啊,直接我们那个运行一下,我们再下个单看一下, 看一下啊,它它的异常,它是个什么异常啊?是不是个 run time 异常啊? 他说他这边是这边文章说的是抛出的是什么一个 run time 的 异常,是不是啊?他是这么一个异常,我们看一下是不是一个异常啊? 就是他这种就肯定是有问题的。你外层我捕获了我的业务异常,帮我处理之后,因为我要处理往外再抛的时候,你抛个 run time 异常,你要把我业务异常再给我抛出去,是不是,对不对 啊?所以这是这里面有也有坑啊,来,就因为我的前段要返回嘛你,我不知道你是因为余额不够才导致的问题啊,那我们的来我们这里面可以下个单来测一下 啊。下个单你注意看是个什么 try to 啊? proceed you will create error 是 不是是个 run time 异常啊?所以这这个坑还挺多的对不对? 好,但是我们整体的话,就说 cata 的 事务呢?帮我们解决这个事务问题,什么问题的?是不是下单的,然后回存回滚,有一张回滚, 对,好,这是这块啊,大家这里面 cata 的 话有更多的一些配置,你像包括啊,我们的叉 a 模式啊, tcc 模式怎么去做啊啊,我都会在后续的实战课程中进行讲解。好吧,这一块的话,就通过这个例子,大家去演示一下我们的 cata 它是怎么去解决我们分布式事务的问题的,所以大家也体验过了。 cata 的 话,你看我们整体去使用它吧,只要把 tc 环形搭好 啊,然后我们去配的话也非常简单,是不是?我们把它配好,然后我们真正去用的话,我们直接怎么直接引入一个 global transactional? 就是 要全句事务对吧?如果是全事务引入这么一个注解,如果是本地事务就是存存事务呢? 就跟我们以前使用什么事务一样的,很方便,业务相当是零侵入嘛,是不是只是一个注解搞定的?所以啊,这是阿里首推的模式啊,你比如你比较简单的业务啊,性能要求不是特别高了啊, 这种情况下,我们其实是可以解决分布式问题的话,我们可以首首选啊,使用这个阿里的这个 c 塔的 a t 模式 啊,这是这个点啊,这关于我们的分布式事物啊,当然啊,这这块配置的话,跟跟着老师思路去配啊,好吧,先搭 tc 啊,然后搭我们的,再搭我们的,整合我们微服啊,然后这块整个这个流程的话啊,要去理解,好吧?啊,好, 当然后续我们还会再继续再去。在我们 cata 里面,在时长课里面还有好几节课啊啊,大概有,包括原码的话有将近七八个小时。啊,要去讲这个 cata 啊,很复杂的啊 啊啊,对,就是会去啊,想去去讲它,我们后面在这个课里面看。好吧,那接下来的话我们就去看一下那个申请到限流啊,比如我,我要限制 你的每个用户去刷单呀,是不是我让他每秒钟最多只能下一单,那这种情况下我们怎么去处理?这是我们可以要引入 sql 下流路径。好这块的话啊,我们接下来就去讲 sql。 好, 关于 set 啊,就讲到这儿。
粉丝3.8万获赞17.8万

hello, 各位小伙伴,大家好,我是北冥,这一讲呢,咱们来聊一下怎么样去回答那关于 mice circle 事物的隔离级别和所机制啊? 那关于这两个点呢?实际上他和 mythical 所以差不多啊,他都是 mythical 去面试的时候他会重要考察的一些点啊,那咱们呢就来跟大家去举例子,然后呢将这两个机制去做一个简单的剖析。 ok, 好,来看第一张图啊,我们首先呢就来去分析一下 my circle 的一个事物隔离级别啊,它呢指的是我们在多个县城,我们去操作这个数据库的时候, 那数据库他要负责隔离操作来去保证,那你各个县城之间你在获取数据的时候,他的一个准确性啊,那在 mysco 里面呢,他是分为了四个不同的 层次,那按照隔离级别的水平高低来去做一个排序啊,那第一个是读未提交,那第二个是读已提交,第三个呢是可重复读,第四个呢是可串形化啊。 首先第一个独位提交,那独位提交呢,实际上是这几个隔离级别里面,那他的隔离性呢,是最低的,也是最弱的, 那它会产生一些问题啊,比如说脏读,不可重复读,还有换读问题啊,所以说它理论上它是存在的,但实际你在工作当中你是不可能去用它的,但它性能呢,反而是最好的。 ok, 那第二个呢是读已提交, 那独一提交呢?他保证的就是我的事物他不会出现一些中间状态的数据,那我所有的数据呢,都是已经提交的,然后呢也是更新的, 那他解决了一个什么问题呢?就是脏读的问题啊,但是就是说你读一提交,虽然解决了脏读,但是他的格力级别呢,还是比较低,因为他是会允许我事务之间可以并发的去修改数据的, 所以说呢,他不能够去保证你再次去读的时候,你还是读到的一样的数据啊,所以说他还是会有不可重复读,还有换读的现象啊。好,那第三个可重复读, 那在 myco 当中, inner d b 引擎它默认的呢?就是可重复读的这个格力级别啊,它保证了,那你在同一个事物当中,你多次读取数据,它会保证你的一致性, 它解决了脏读和不可重复读,但是它还存在一个什么?存在一个幻读的现象啊?好,那最后一个呢,是可串形化,那可以看到它框里 已经没有任何东西了,对吧?那所以说他解决了脏读,不可重复读,还有换读,但是我们要知道那可串形化他就意味着一个现象,我去读取数据的时候,我要先去获取这个共享读索,那我更新数据的时候,我要先获取这个排他写索。 如果说我们 circle 语句当中使用了这种 well 语句啊,那他还会获取什么?获取这种区间锁,那换一句话来说呢,就是我事务 a 在操作数据库的时候,事务 b 他只能够什么排队等待,所以说他的性能呢,也是最低的一种啊。 好,那至于数据库锁呢,他其实有很多啊,那比如说那分为了悲观锁,乐观锁,对吧?那悲观锁他的思想是我认为这个数据他很有可能会产生冲突,所以说我先给他去锁上,而乐观 关锁呢,他是认为我数据出现冲突的可能性,他不是特别大,那我呢,可以先不锁,我在更新的时候呢,我再去做一道检测。那悲观锁和乐观锁在 mysac 数据库当中,那他是怎么样去应用开发的呢?是怎么样去实现的呢? ok, 非常简单啊。那悲观数我不知道大家有没有用过,就是你查询语句上面,你在查询语句上面,你用到的这些 select 语句,你加一个 for update, 你这样呢,你就能够去实现一个悲观锁啊。而乐观锁呢,它采用的是一种 c e s 的机制,它就是我不会对数据加速, 而是我去比对这个数据的时间出啊,或者说是版本号啊,我去做一个版本的判断,那这个版本号有没有被更新过,如果这个版本号没有被更新过,我就能修改,如果更新过了,那我就不能修改了。 这个呢,就是 mysel 口的这种事务,格力级别和锁机制啊。但是如果说啊,就是说面试官他想去深挖,那你对数据库这种内部机制这种掌握程度,那么他的切入点呢?一般他是从 mysel 口的事务和锁机制,也就是我们刚刚提到的。 那接下来呢,那我们就从这种初中级的这种工程师角度出发,我们从刚刚讲到这些概念,然后呢我们再来去讲一讲实践,带大家去聊一聊这两个点之间的一些高频考点啊。好,首先呢就来聊第一个怎么去理解章读, 然后还有不可重复读,还有换读问题啊,那刚刚在讲中格力级别的时候,我们就讲到了脏读,对吧?那脏读是什么呢?脏读就是我读到了你还没有提交的数 据。我们假设在下面这张图中有事务 a、 事务 b 两个事务啊,那么在并发的情况下,事务 a 呢?他先开始,那他开启了一个事务,读取了商品表当中的数据,对吧?然后呢,他更新了商品表当中的数据,如果这个时候事务 a 他还没有提交, 那恰好事务 b 呢,他也开始了事务,然后呢,他读取商品数据,那他读到的是刚刚这个事务 a 更新之后的一个数据啊,所以说,那那在这呢,就会产生一种情况啊,就是 如果我事务 a 触发了回滚,那么我商品数据是不是会变更为原始数据,对不对?那我事务 b 我读到的数据,他就是一个错的数据啊,那这个现象他就叫一个赃读啊。那赃读,那在面试当中呢,他的一些关注点在哪呢?就是 首先他对应的隔离级别是什么?就是独位提交,那刚刚也讲过了,对吧?因为只有在这个级别下,他才会出现赃度,那第二个,那赃度怎么去解决?非常简单,就是你提升这个事物的隔离级别,比如说你将这个独位提交改成独一提交。 好章读,聊完了呢,再来聊聊不可重复读啊,那不可重复读是什么呢?来继续看下面这张图啊,假设两个事物,事物 a, 他事物开始读取了商品表的数据,对吧? 让他读取了一条数据,然后呢,他就去执行了一些逻辑,那在执行逻辑的时候呢?事务 b 他也开始了失误,那他呢?去更新了这个商品表的数据,然后事务 a, 他执行完逻辑之后,他可能他的需求还要再次读取商品表的数据,然后呢,他就再读了一遍,他读的 之后,他会发现我这个数据他不匹配,然后呢,我这个数据读到的和我上一次读到的他不一样,那这个现象呢?实际上就叫做不可重复读啊。 那不可重复读,他关注的考点是什么呢?我们去理解他这个概念啊,就是我两次读取数据的中间被别人修改过,对吧?那对应的格力级别是什么呢?就是读未提交,或者是读已提交,他都会出现,那怎么去解决这个问题呢? 还是老方法升级隔离级别,你将这种独位提交或者是独位提交改成可重复读,那么就可以去避免这个不可重复读的问题啊。 ok, 好,那再聊聊第三个,那就是什么?换读, ok, 换读是什么呢?换读它指的是啊,就是我们在一个事物当中,我们同一条查询语句 在不同时段执行,得到的结果即不一样。这个是什么意思呢?我们跟大家举个例子啊,假设事物 a, 我开始了,我读取了一次商品表,对吧?然后我最后得到的 id 是什么?大家的 id 是三, 然后事务 b 呢,他也开始了,他也同样的读了一次,那他得到的 id 是什么?得到的 id 也是三。 ok, 那接下来事务 a, 他先插了一行数据,然后他读了一下,那读到的 id 是什么?读到 id 就变成了四,对不对?刚好是 id 三加一嘛,对吧?然后事务 b 呢,他也差了一行数据, 那接着他会去读最新的 id, 那最新的 id 是什么?他不是三加一了,他变成了四加一了,所以说他读到的 id 是五了,这个时候我们会发现,我们再去使 用这种 id, 我们去做判断,或者说做一些关键数据的时候,他就会出现这样的问题啊,那这个现象呢?他其实就有点像让事务必他产生了一种幻觉, 我读取到了一个就是我自己都意想不到的数据啊,所以这个呢就叫做幻读。当然啊,你不仅说是只有新增,你删除啊,修改啊,也会发生类似的这种情况啊。 ok, 那再聊聊幻读,他的一个面试的一些关注点啊, 就是我们如果想解决患毒,那我们肯定不能就是说还像以前那样把事物隔离级别去提升到这种可串型化, 因为你提升到可创新化,那就意味着你的数据库他失去了并发的处理能力。然后第二个呢,就是行锁,但我们要知道,行锁他实际上是解决不了贩毒的,因为 为我们即使那我锁住这些记录,但是你还是不能够去阻止我去插入一些新的记录,对吧?那第三个 我们要解决患毒的办法,那是怎么样的呢?就是我们可以去锁住这种记录之间的间隙,所以说在 mythical 的 innodb 当中啊,他引入一个锁叫做间隙锁啊, 所以我们在面试的时候呢,就是你也要去了解一下间隙锁,因为你在打这种锁机制啊,或者说格力级别的时候,他也都会聊到啊, 然后呢,还不仅是说是间隙所,还有间隙所跟航所的这种结合, ok, ok, 那除了格力级别呢,实际上很多的同学在面试的时候,他经常会被面试观众直奔主题的去问啊,他就是说你贪, 就是谈一谈你对思索这种理解啊,对吧?那这个是一个比较开放性的问题啊,就是你要回答的时候,你可能要去梳理一下你你的一个回答的思路, 那就是你要从几个角度去回答,比如说思索他怎么样产生的?那第二个呢?怎么样去避免思索? ok, 首先呢我们就来跟大家去聊第一个点啊, 有两个县城,两个资源,对吧?那思索他发生一般都是在多县城,那他的必要条件呢?就是你必须是两个或者两个以上,这种执行的过程当中啊,因为争夺资源,他才会去造成这种县城之间的这种相互等待,所以这种情况呢,他就会产生一个思索, 就比如说啊,我有资源一,资源二,我有现成 a, 现成 b, 对吧?当现成 a 他已经获 取到了资源一的情况下,那我我我想去获取这个资源二,但是在这个时候我现成 b 已经拿到了资源二,我也想去获取这种资源一,那现成 a 和 b 的状态,他们就变成了一种相互等待的这种思索的状态啊, 如果说在没有外力这种干预的情况下面,你线程 a 和线程 b, 那你就会一直的互相等待,然后呢你这两个线程就卡住了,你没有办法去处理一些其他的请求, 所以说这样呢就会造成一个死锁啊。 ok, 那我们讲完了这个例子,我们再来去系统的去跟大家去讲一下产生死锁的几个必要的条件。 ok, 来讲第一个护持条件,那护持条件呢?他讲的是我多个县城,我不能够同时使用一个 资源,比如说我县城 a 已经持有了资源,对吧?那他不能够再被县城 b 所持有。如果县城 b 他请求获取县城 a 已经占有的资源,那么县城 b 呢?他只能够去等待,他等待这个资源被 a 释放掉,他才能占有。 这个呢,是第一个护持条件啊。那第二个是持有并等待。当我们现成 a, 他已经有了资源一,对吧?然后又要申请这种资源二,但资源二呢,已经被这种资源 c 他占用了,所以现成 a 呢,他就会处于一个等待状态, 但他在等待这个资源二的时候呢,他又不会去释放这个已经拿到的资源一。 ok, 这个呢,就是持有并等待。 ok, 那第三个点,那就是不可剥夺条件。 不可剥夺条件是什么呢?就是当我现成一,我在获取到这种资源一的时候,在我自己我使用完之前,他是不能够被其他现成占领使用的。如果我现成 b, 我也想使用,那么怎么办呢?我必须等现成 a 使用完之后,他主动释放 才能够去获取啊。 ok, 那最后一个点,也是最关键的一个点,循环等待就发生死锁的时候,你必然会有一个现成,也就是我形成一个资源的环形链。 什么意思呢?比如说我现成 a 已经获取到了资源一,对吧?但同时我又请求获取资源二,而现成 b 呢,我已经获取到了资源二,但是我又同时请求获取资源一,那这样就会形成一个现成 和资源之间,他请求等待的一个环形图啊。好,这个呢,就是循环等待,那思索只有满足了这四个条件,他才会去发生啊。那并发场景下面,你如果说你一旦思索了,一般没有什么特别好的办法, 那很多时候呢,你只能够你要马上解决的话,那么就重启,所以我们要去规避思索的话,那具体怎么做呢?就是 他刚刚满足,是不是有四个条件,对吧?那我们去破坏一个不就可以了吗?对不对?但是破坏也是有条件的,就是 你的互斥性,你是不能够被破坏的,你这个是没办法被破坏的,但是你其他的你是可以破坏的。比如说我持有病等待,那我是不是可以我先一次性的我把资源都拿到了,那这样我是不是就 没有这种等待一说了,对不对?我在跑这个业务逻辑的时候,比如说我现成 a, 对吧?我先直接把一二次元拿到,我再去执行业务,如果没有拿到,对吧?那我就报错嘛,对吧?或者说我去做一些其他的规避性的处理嘛, 对不对?这样也就破坏了。那第二个呢,从不可剥夺性出发。首先我们要知道就是我占用的部分资源的线程, 我在进一步去申请其他资源的时候,如果没有申请到,那么就主动释放我已经占有的资源,这样呢? 我这个不可剥夺的条件是不是就破坏了,对吧?我现成 a, 我拿到了资源 e, 我在拿资源二的时候,如果我发现了我拿不到资源二,那么我就把资源一释放,那这个时候他有个先后顺序,我现成 b, 我发现,哎,这个资源 e 我还是能拿到的,那这样是不是就解决了死守 的问题,对吧?好, ok, 那最后一个点啊,就是循环等待,那循环等待呢?我们这个点怎么破坏它呢?就是我们可以按照 顺序申请自愿来去预防啊,就是我们去按照有序的分配原则,比如说我让自愿的申请和使用他们有一个线性的顺序,那么在申请的时候呢,可以先申请这种序号小的,再申请序号大的,就这种线性化的操作,他就不会存在循环的。 也就是我现成 a, 我需要一二资源,对吧?那我现成 b 也需要一二资源,我们都按照同样的方式去获取, 假设我现成 a, 我获取资源 e, 那我现成 b 也是获取资源一,而不是说先获取资源二,那这样的话,我只要有一个抢到了,我就能够去抢第二个,对不对?那这样呢,也就破坏了这种循环等 简单的条件。好,那这个呢,就是本讲关于这种 mystical 事务隔离级别还有所机制的一些讲解。啊,那本讲内容呢,咱们就聊到这,那咱们呢就下一讲,再见。

你知道买鞋口中的至尊锁吗?比如说我们的主见 id, 他是至尊的,我们现在开了左右两个窗口,我们先在左边去开始一个试物,然后我们这时候去插入一条数据,比如说这条数据叫做试, 我们在这里去插入一下,然后现在保存的他的主机 id 为四,然后我们再在右边这个窗口也去同样的去开启事务。那么我们在这时候,比如说我们去刷新啊,然后会发现这边依然是三条,因为我们左边的事务还没提交,所以说右边查出来还是三条,那么我们这时候再去插入一条数据, 比如说我们在这里去插入一条叉叉,然后我们去保存一下,这个时候会发现变成了五,你会发现在买些个默认的可重复读隔离级别中,虽然我们查不了左边的这个四的数据,但是他的一个至尊是根据这里跳过的,从五开始的。 如果说这个时候我们想强行插入世界的数据,我们看行不行呢?比如说这里我们去保存下这里就会发现他一直在转圈圈了,这就是买 c 口中的指针锁。如果说我们把左边的这个事物给提交了, 然后就会发现右边这个报错了,他会说我们的主机 id 四已经重复了,然后我们这里点就好,我们在左边再去刷线下,然后在右边我们去还原,然后这个时候我们再去提交下刚才的事物,然后这里再去刷线下,会发现这条五就出来了。

仅需两分钟保定 cinter nice 底层枷锁原理 cincter nice 是找歪中并发场景下用于实现资源同步管理的关键字。他提供了对对象或方法的原子性访问, 说白了就是在同一时刻只能有一个现场访问该对象。他可以修饰奥迪克对象,像这样他也可以修饰实力方法,像这样,此时是锁了。第四项,他还可以修饰静态方法,像这样, 此时他锁的是当前类的科尔斯对象。那赛格 nice 底层到底如何实现的?其实他的原理主要基于对象头和金石器进行实现。 那对象头又是什么呢?对象头其实就是这个对象在内存中的存储结构包含的对象头信息。这个中每个对象都有固定格式的头。对象头包含马尔国标记和 cos plant 的原数据指针, 所相关的信息就存在猫儿国有,其中就包含了直项所记录的指针,用于实现所的获取和释放。在六十四位的虚拟期中,猫儿国有六十四个 bt, 像这样其中使用一个 b 标志是否偏向所 两个必定来做锁标识?所以塞克尔南一次枷锁就是修改这两个锁标志位的数值,县城都是根据这个所标志位的数值判断这个对象是否上锁。那监视器又是什么呢? 在招牌中,每个对象都有一个监视器 monak 与执行关联。 monak 内部维护了一个等待队列威塞和一个同步队列 ntac。 当一个县城尝试进入一个被 thinker nice 修饰的代码快货方法时,他会尝试获取对象关联的 monitor。 如果这个 monitor 的锁没有被其他县城持有,那么当前县城就会获得锁并进入临界区,否 则现成将进入同步队列或阻塞等待状态。因此,这个中的塞口人机枷锁原理主要就是通过更改对象头中的所标志文,并配合按着他监视器进行实现。点赞加关注,马上带你上高速!

面试官问,你知道大失误会带来什么问题以及如何解决吗?首先要明确,大失误就是运行时间较长、操作数据量较多的数据库事务。想要查询执行时间超过十秒的大事务,可以用如图所示的哨口语句 来查询。这类事务会给数据库带来三个核心问题,第一个是锁定数据过多导致实锁和锁超时。在一个 d b 中,不同事物若出现循环资源依赖比 与事务 a 先更新 id 等于一的行,再尝试更新 id 等于二的行。事务 b 先更新 id 等于二的行,再尝试更新 id 等于一的行,两者就会相互等待对方释放锁,陷入死锁。而处理死锁的默认策略中等待超时时间。 inner db lock wait turn out, 默认是五十秒过场,会占用资源,改短又可能影响正常死锁消除。 实所检测虽默认开启,但它的时间复杂度是 o n。 上千个兵发现者更新同一行时,会消耗大量的 c p u, 导致事务执行效率较低。第二个问题是回滚记录占用大量的存储空间,且回滚时间长,每十个钟数据更新时会记录回滚操作,这是多版本兵法控制的基础。比如一条记录从一改成二、 三、四,回滚日期会记录四到三,三到二、二到一。不同的 review 能通过回滚操作获取对应的版本数据,但这些回滚日期 要等到没有更早的 review 才会删除。大事务会产生大量的回滚记录,既占用存储又减产回滚时间。 第三个问题是执行时间长,造成主重延迟,主库要等事务执行完才写入 b log 传给备库,若主库事务执行十分钟,备库可能延迟十分钟,影响数据一次性。为了验证实锁和手刹时这类问题, 我们可以做一个简单实验,在 mac 应用 d b 环境中创建测试表 t, 并插入 a 等一、二两条记录。首先开启事务 a 执行 begin update t, set key 加一, where id 等于一,此时四五 a 持有 i 等于一的函数。接着开启四五 b 执行 begin, update t, set key 等于 k, 加一 where id 等于二、四五 b 持有 i 等于二的函数。随后在四五 a 中执行 update t, set key 等于 k 加一 where i 等于二,四五 a 开始等待 四五 b 示范 i 等于一,四五 b 开始等待四五 a 示范 i 等于一的函数。此时数据库会检测到实数 锁,其中一个事务会被终止,并返回实锁。提示,若敲着 in a d b log wait time out, 参数为十秒。重复上述前三个操作,即事务 a 持有 id 等一的锁,事务 b 持有 id 等二的锁,事务会尝试更新 id 等二的记录。事务 a 会进入锁等待状态,十秒后等待超时,并返回 锁超时错误依次验证大事务中所冲突引发实锁和锁超时问题,针对这些问题有多种解决方法。基于 in a、 d b 两阶段锁冲突引发实锁问题,针对这些问题有多种解决方法。基于电影票交易业务,将 高冲突的增加隐约余额操作放在记录交易日制,扣减顾客余额之后,缩短高冲突锁的持有时间,减少锁等待。针对实锁检测的高 cpu 消耗,可参考康可瑞的 hicmp 的 分担锁设计, 把档案数据拆分为多项,比如隐约账户余额拆分为十条,记录余额为十条之合,每次更新随机选一条,冲突概率降低为十分之一,注意退票等余额减少。场景需特殊处理。还 还可以调整事务隔离级别,把默认的可重复读改为读体校,此时更新己所单行,避免见义所或表所,但要配置 be log 格式为 wrong, 防止数据与日期不一致。此外,纯止读操作,无需开启事务,可通过 set master execute time 限制语句,最长执行时间监控 information schemer the db prints。 表设置常事务阀值,超阀值时告警或终止事务,测试时输出兼容 log, 提前排查潜在的大事务。设置一个 db android tab space, 分 离 android log 表空间,方便清理大事务产生的超大回滚段。这些补充方案也能有效缓解大事务问题。面试中,回答这个问题 要抓住核心逻辑,先明确大事物的定义和查询方法,再结合底层原理讲清楚三个核心问题。实所所说源于循环所依赖回馈。日制问题与 m v c c 机制强相关,主从言辞则和 b log 同步逻辑有关。接着针对这个问题给出对应的解决方案,重点结合具体场景与 电影票交易,隐约账户拆分说明是抄袭,让回答不空洞。最后补充易错点,比如调整隔离级别,必须配套设置 bingo。 伪乱分段所设计要处理特殊业务场景,同时提及监控和提前排查措施,形成定义问题原理,解决兜底的完整应答,既体现对知识点的掌握,又展示实际应用能 力。刷题面试不用慌,发古文宝典进群免费领,谢谢观看关注我求知不迷路?

对于如何在布加索的情况下去解决现在安全问题啊,看看普通人和高手是如何回答的。普通人的回答,呃,布加索如何去解决现在安全问题? 一般解决现在安全问题的方式呢?我们都是需要加锁的,不加锁,不加锁好像不是特别清楚。 高手的回答,好的,对这个问题呢,我会从三个方面来回答。第一个,所谓的现在安全问题啊,其实是指多个现在同时对于某个共享资源的访问导致的原则性、 可见性和有趣性的问题。而这些问题呢,会导致共享数据存在一个不可预测性,使得程序在执行过程中呢,会出现一些超出预期的一个结果。第二个,一般情况下, 解决现在安全问题的方式是增加同步锁,常见的是像 single, nice, rock 等等。由于导致现在安全问题的根本原因啊,是多现成并行访问共享资源。对共享资源加锁之后呢,多个现在访问这个资源的时候必须要先获得所, 也就是先获得访问资格。而同步所的特征是在同一个时刻只允许一个县城访问这样一个资源,直到所被释放。 虽然这种方式呢,可以解决现在安全性的一个问题,但同时带来的是加锁和释放锁所带来的一个性能开销,因为加锁会涉及到用户空间到内核空间的一个转换以及上下纹切换。第三个啊,如 如何在性能和安全性之间去取得一个平衡,这就引出了一个无所并发的一个概念。一般来说呢,会有以下几种方法。第一个是通过自选锁,所谓自选锁是指现成在 没有抢占了锁的情况下,先自选指定的次数去尝试获得所。第二个是乐观锁,给每个数据去增加一个版本号,一旦数据发生变化,则去修改这个版本号。那在加号里面呢,有一个叫 cis 的一个机制,可以去完成乐观锁的一个功能。第三个在程序设计中呢,尽量去减少共享对象的一个使用, 从业务上去实现隔离,避免批发。以上呢就是我的一个回答,好的,看完高手的回答之后呢,相信每一位看完视频的小伙伴对于现在安全问题呢,有了更深刻的一个理解。 本期的普通人 vs 高手系列的视频就到这里结束了,喜欢的朋友呢记得一键三连加个关注,我是头发很多的陈炫麦,咱们下期再见!

今天我来给大家讲一下如何通过两个注解来解决 spring 多现成事物失效的问题。 这个问题说白了其实很简单,是因为 spring 的 事物是基于 spring 的 local 来实现的,所有的事物相关的信息都会存在这个现成的 spring 的 local 里面,那么这样就会导致一个问题, 当一个县城开启事务之后,这些信息只存在于该县城的私人的 logo 里面,其他县城它是无法获取到的。还有更多针对二零二五年新变化的题目,我整理成了九十万字文档,里面有大量场景题和求知高频面试题、评论区扣六六六领取。 因此当我们在一个有 transnational 的 注解的方法里面去创建新的县城,执行数据库操作的时候呢,这些新的县城它是没办法去获取到主县城的事务的一个上下文的,导致这个事务就直接失效了。 我们通过这个代码来分析一下,当我们的一个客户端在调用这个 parent 方法的时候,就会通过这个 transnational 的 注解开启一个事务 这个事务的 connection 的 连接对象,它就会存储到我们的一个主县城的所有的 local 里面。接着我们再去调用这个迭利的方法,去数据库里面去删除 id 唯一的一个记录, 此时这个删除操作它是属于这个主县城里面的。再接着往下,它会去调用这个叉 o 的 方法,这个叉 o 的 方法呢,它会去创建一个新的县城,因为县城之间所有的 local 它是不共享的,那么子县城肯定获取不到主县城里面的 connection, 所以此县城的执行操作它是一个单独的操作,那么单独的失误之间肯定是没有影响的,也就会导致我们这个失误失效。 解决这个问题的办法也有很多种,我们这里呢通过注解的方式来解决,我们只需要在主县城的接口上添加一个 men transaction 的 注解,在此县城上添加一个 some transaction 的 一个注解。我们看到后面的代码。 在这个 main 圈灾的注解里面呢,我们需要去指定一个子县城的一个数量,它的一个参数,我们这里有两个子县城,那么就填一个二进去。 接着我们的子县城上面呢,就要去添加上这个 sun 圈灾是哪个注解?表示这是一个子县城接口。在这里我们开启县城的一个方式,就从一个 new thread 改变成了这个 sink 的 一个注解, 这样我们的这个子县城里面发生了异常的话,我们的代码依然是能够保证我们的一个事物一致性的。那么这个注解是如何实现的呢?简单来说就是我们会在主县城里面去维护一个是否要去回顾那个状态,每个子县城他都会去开启一个当断的事物来做处理。 我们这里有三个子线城,那么他就会去开启三个独立的一个事务,当他们执行完自己的个业务逻辑之后呢,他不会立马去提交我们哪个事务,而是去通知我们的主线城执行已经完成了,并且等待我们这个主线城做最终的一个决定。 如果子线城他们都执行成功了,那么主线城呢就会发起一个提交命令,让他们子线城都去提交我们那个事务, 如果子县城里面有任何一个执行失败了,那么他就会将这个大局状态设置为处主县城呢,他就会根据这个状态就会去发起一个回滚命令, 所有的子县城都会去接受到我们这个命令,然后他们就会去做这个回滚的一个操作。这种方式呢其实就是二阶段的一个提交思想,那么我们就来看一下这两个注解它是如何实现的?我们直接通过代码来分析, 在这个代码里面我们添加了这个 m 春加省和这个 sun 春加省,接着呢再添加了一个 a o p 的 一个类,这个 a o p 的 类呢,其实就是对我们的这个 m 做一个增强,还有呢我们的这个 sun 做个增强。 那么再看到我们的这个业务代码在这个代码里面呢,首先我们会在这个主县城里面,哎去做了一个删除操作,我们在这里呢需要把我们当前县城传进来, 点到我们这个 child 里面,在这两个 child 里面呢,我们第一个它就加了我们这个 song 的 一个 creation, 还加了我们这个 spring 它的一个 creation 的 一个注解,下面的一个 child 二也是一样的,在这里呢我们的这个 child 一 它会去做一个一除以零的操作,那么它这一个表达式会抛出一个异常, 接着这两个 child 的 方法它都添加了这个 sinc 的 入解,也就说我们这两个方法它会去通过独立的县城去进行一个执行。好,接下来我们就通过 debug 的 方式来看一下我们是怎么通过这两个注解来实现的这个事务一致性的, 我们直接在这个地方打个断点,还有在我们这个嵌在事务里面,我们也需要去打上对应的一个断点,打完断点了之后呢,我们直接去请求下我们的这个接口。 好,此时请求了接口了之后呢,它的一个断点就已经成功走到我们这个 main 方法里面。好,我们在这个地方成功请求了之后呢,它就已经走到了我们这个 main 的 一个增强方法里面,因为是一个 around 的 增强,所以我们这一个代码它肯定是会在我们的这一个业务方法之前进行一个执行。 好回到这个 main 的 一个增强方法里面。在这里呢,首先我们先会去获取到当前现成它的一个 name, 接着呢,我们需要去初步化这个事物协调的一个控制对象,它是要先去记录一下我们这个 main 县城它的一个数量,我们需要根据它来做提交或者是回滚的一个策略。接着再往下呢,我们会去记录一下我们这个 sum 它的一个县城它的一个数量, 这个县城的数量呢就是从我们这个 main chain zhai 它的一个注解上面去获取到。我们可以回头看一下我们的代码,在这上面呢,我们就指定了为二,也就是说我们这里子县城 子事务它有两个,那么我在这里呢,就要需要指定两个。好,接着再往下,我们需要去指定一个标记,这个标记呢是一个 rowback 的 一个 flag, 如果它为 false, 那 就说明我们的事务它是不需要做回滚的。如果它一旦修改为簇拥之后呢,它就需要去做回滚,如果我们的子线段它出现了问题,那么我们就要去修改这个全距边量,接着再往下呢,我们需要去记录这个异常它的一些信息, 如果我在执行过程中出现了异常,那么需要把这个异常添加到我们这个向量里面去。接着再往下,我们就需要把刚刚创建出来的这些信息呢,保存到一个共享的 map 里面去,共此事物去使用,也就说我们这个信息它都是一个局共享的。接着往下走, 在这里我们就已经成功把这些信息添加到我们这个 map 里面去了。添加完成了之后呢,我们再通过这个 join point 去执行我们这个主事务它的一个方法,我们点到这个 proceed 里面,在这里呢就是我们这个 spring 它的一个逻辑了,我们点到这个 proceed, 再往下走 inwalk join point, 再点到这个里面,再往下走,再往下走,走到我们这个 inwalk 的 方法里面。好,此时可以看到我们的一个断点就已经成功走到我们哪个业务方法里面去了,此时我把断点一放, 那么就可以看到我们就已经成功走到了这个 sum 它的一个增强方法里面,因为我们在这个地方呢,它需要对我们添加了这个 sum transaction 的 一个方法,做一个 around 的 一个增强, 那么我们在这个地方呢,就会去获取我们方法的参数,最后一个参数呢,应该是我们的这个现成对象,在代码里面呢,我们已经把主现成传入到了我们的这个参数里面,所以我们在这个地方它就会去获取到我们的这个主现成,获取到了之后呢, 我们就可以拿到它的一个名字,去我们的一个共享 map 里面获取到我们当前这个主事务它的一个状态。此时我们在这个地方它的一个 control down, 如果等于呢不存在的话,就说明我们根本就没有添加这个 men 圈加上的一个注解,那么它就会直接去执行我们的一个子事务的一个方法了,它就不会去参与我们的一个分布式的一个事务协调 好,那么这里我们已经添加了这个注解,它就会走到这个地方来,那么它就会去获取到我们这个 sun, 它的一个 counter latch, 还有我们这个 beception, 它的一个向量。在这里我们获取到了相应的一个信息了之后呢,就可以对它进行一个判断。 如果我们执行的一个子县城里面出现了异常,那么它就会把这个 rowback flag 修改为 true, 那 么我们在这个地方它如果为 false 的 话,那么它就不会执行我们这个逻辑了, 如果它为一个处的话,就说明已经有现成出错,当前现成不需要再去执行我们那个事务方法,那么在这里呢,我们通过一个编程式的一个事务方式去开启我们那个子事务,这个子事务呢,它是在独立的一个事务里面去进行执行的,它不会受我们主事务的个影响 直接往下走,开启了失误之后,我们就会去执行我们此失误的一个方法,我们点进来,继续点进来,继续点进来,点进来, 再走到这个里面,可以看到他就在执行我们这个 child 一 的这个方法了,当他删除完我们这个 id 为二的记录的时候呢,就会执行我们这个一除以零的操作,在这里他就会去抛出一个异常,可以看到我们在这里 throw 一个 exception, 接着跳出来, 在这个里面呢,在执行我们子事务方法的时候,它会做一个 try catch, 捕获到我们的一个异常了之后,它就会把我们那个异常添加到我们这个异常向量里面。接着呢,再把我们这个本地事务做一个 rowback, 做个回滚,在这里它就会把我们的这个大局回滚标记设置为处。 当其打的现成感知到了我们这一个状态的变化了之后呢,它就会做一个对应的一个回宫操作。好,接着再往下,再把这个 man 到 lynch 去,把它做一个 ctrl down, 做一个减一操作,此时它就会从一减到零,接着再往下,我们这个桑 control lynch 呢,它为二啊,再减一就变为一,因为我们当前 只执行完一个现成,还有一个现成没执行完,所以我们需要等到我们这个 control down 呢啊,从二减到零, 好,接着再往下,我们锻炼走一下,走到第二个县城,好,那么当我们在这个地方把这个 rowback flag 改为了处了之后呢,当第二个县城,当这个 child to 他 进来我们这一个方法里面的时候,他就会走到我们这一个地方来, 走到这一地方来,他拿到我们的一个状态,他为处,那么他就不会再去执行我们下面的一个业务方法,他直接在这个地方 written 掉了。 好,那么我们这个三到 lynch 它减到为零的时候,我们的这个 main 县城它就会继续在运行在这个地方。当我们这个 main 县城它执行完成了之后呢,它会走到我们这一个地方来, 它会在这个地方调用一个 i v t 阻滞住。当我们所有的子线段它减到零的时候,执行完成的时候呢,它就会继续往下走,走到这个地方我们的这个 mendel lynch 它就会看得到减到零。好,那么此时如果有子事物它已经执行完成了,但是它没有提交,那么它会阻滞到哪个地方啊? 它会阻塞到这个地方,它会等待我们这个主事务做一个决策。当我们主事务它把这一个数量减为零的时候呢,这里的一个 i v t 就 它就会放开,那么我们这个子事务它就可以根据我们这个回滚的一个 rowback 的 一个 flag 去决定他是要去做一个 rowback 操作还是做一个空密的操作。那么这样的话,我们就能够去通过这两个事物来保证我们的一个事物一致性。那么这个代码呢?大家可以根据我的这个流程图来做一个对照,这样的话大家就能够理清自己的个思路了。