粉丝329获赞1582

当面了个四年后端,我问他分布式事务怎么保证一致性,他脱口而出,用 sitit 模式啊,二阶段提交,要么全成功,要么全回滚。我点点头,接着问他一个场景题,好,假设你们用 sitit 处理订单,支付用户下单成功,扣库存、加积分、发优惠券。三步操作执行到第二步时,网络抖动, cata 超时触发全局回滚。但第一步扣库存已经提交了 cata 通知,库存回滚时,发现库存被另一个事物改了,回滚失败。现在库存扣了,积分没加,优惠券没发,你说要么全成功,要么全回滚,现在算什么?他愣了一下,可能是脏血, cata 没法自动恢复。 我追问,那现在线上数据对不上用户投诉,你指望 cata 帮你修好,还是自己写脚本补数据?他开始吱吱呜呜,面试也直接结束了啊啊! 这正是分布式事物的回滚陷阱。你以为用了 cata 就 能高枕无忧,却不知道回滚失败时,框架只能告诉你,我修不了,剩下的得你自己扛。如果你对这问题也不了解,我整理了让面试官沉默的大场必考题库, 包含 jvm 夺命连环问、 spring 灵魂八谷高并发必杀场景、 radis 深度陷阱,给个三连扣个 pdf 打包带走 nice! 为什么这个问题能筛出高手?因为他考察的不是会不会用 cata, 而是有没有深入理解分布式事物的底层机制,以及回滚失败时的兜底方案。一个能真正扛住分布式事物的后端,必须建立三层防御,第一层,理解 cata 的 回滚机制,知道它会失败。安 du log 原理, c 塔 a t 模式,通过记录 android log 实现回滚,回滚时根据日制反向补偿,但如果回滚时发现当前数据已被其他事物修改, c 塔无法自动覆盖,只能抛异常脏。写场景。 回滚时数据被改了,可能是其他业务更新了同一行,也可能是重试导致重复执行,这种情况 c 塔无能为力,需要人工介入。 适用场景, a t 模式适合并发冲突较低的业务,比如订单创建、积分发放,不适合高并发热点数据,比如秒杀库存。第二层,业务设计上减少回滚概率。事务边界尽量小,能放在事务外的操作尽量放外面, 比如扣库存前先查库存是否充足,这个查询完全可以放在事务外。可补偿的业务设计,对于关键操作,设计成可补偿的, 比如扣库存失败时不是回滚,而是发起库存释放补偿、操作密等。与重试所有接口必须密等重试机制,保证最终成功,减少回滚触发概率。第三层,都抵御监控, 出了问题能补救。定时对账,每天凌晨跑批,把订单表、库存表、积分表的数据捞出来比对,发现不一致的自动补偿或人工介入。 死信对列,回滚失败的消息进死信对列。人工处理时,要能清晰判断是第一次失败还是数据冲突。 业务妥协,和产品沟通。有些场景可以接受短暂不一致,比如积分延迟到账,优惠券稍后补发,给系统留出补偿时间。厉害!所以这道题考的是什么?它考的是你有没有从用框架升级为懂原理、能兜底的工程思维。 普通开发觉得用了 cita 就 高枕无忧,而高级工程师知道框架只能解决理想情况。真实世界里数据会被脏,写回滚会失败,系统会超时。

今天面了个号称精通 cata 的 后端简历,写着千亿级分布式事务经验,主导过电商订单系统重构。我随口问了句, tcc 模式里空回滚和悬挂事务怎么防,他愣了三秒,说踹失败了就不回滚呗,框架会自动处理的。 再追问,如果踹因为网络超时没收到响应,但实际在数据库里成功了,这时候协调者发起了 cancel, cancel 先于后续的补偿请求到达,怎么处理?他直接沉默了,接着问悬挂事物会导致什么后果,吱吱呜呜说可能资源没释放,但具体怎么排查,怎么兜底完全说不清。 现在面试早就不问两阶段提交理论了,全抠落地坑。很多人把分布式事物当黑盒,只会调 at global transactional 注解,根本不知道空回滚会让资源永不释放,悬挂事物会让订单和库存对不上。要是这类题你也没思路,不妨看看我整理的后端面试题库, 参照大厂初级到中高级后端工程师的能力模型,包含市面百分之八十场景题内容,只要你是我的粉丝,甩个六六六直接带走。学习 nice 高手答这类题都靠这两套系统化思路,直接戳中面试官痛点。第一套,防空回滚。三、满腐核心是让 console 只能回滚,已确认的 try 拒绝无效操作。 一、事务日制先行 try 阶段写本币日制加唯一锁影防重复。二、 console 前置校验。 console 前查日制,无以尝试则直接返回成功,有则执行回滚并更新状态为已取消。 三、 confirm 同理防御 confirm 前查日制不踹或已被看守则拒绝并抛异常配合 radis 缓存热点状态加速叫咽防乱序时空回滚。第二套防悬挂事物六、道闸,解决看守先于踹到达的逆序静态问题。 一、 cancel 先到则写 radis 悬挂标记并记录告诫。二、 try 执行前检查标记,若有则直接拒绝执行并清理标记。三、所有参与者接口设三秒超时,超时后协调者主动发起 cancel。 四、事务日记加版本号, 更新时带版本条件,防止就请求覆盖。五、定时扫描超时十分钟未完成的悬挂记录,人工兜底修复。六、压测模拟 cancel 𠮿 的 网络乱序验证防御机制。牛逼 牛逼!这两道题考的不是你背过多少分布式事物的理论,而是你有没有在生产环境真正踩过空回滚和悬挂的坑。面试官想听的不是 cita 支持,而是我遇到过什么怎么解决的分布式事物的核心不是被说,而是预判超时重试乱序下的一致性问题,以及兜底方案的完整性。 最后问下你线上遇到过悬挂事物导致订单已取消但库存没释放的惨案吗?评论区见。下期讲怎么用 rocket miller 的 失误消息,低成本替代 tcc, 避免空回滚烦恼。

刚面临一个四年经验的后端,我问他,以跨银行账户转账为例, a 库扣款、 b 库加款,从流程设计到异常处理,再到最终一致性保障,你怎么在工程上落地?他想都没想就说用 cata 的 at 模式或者 tcc 框架会自动回滚,保证两个库要么都成功,要么都失败。如果这道题目你也不会回答的话,我整理了让大厂 hr 沉默的必考题库, 扛盖 jvm 夺命连环问 spring 灵魂八谷高并发症必杀场景 radis 深度陷阱最新 java 加 ai 面筋试梯点个赞,评论区来个五五,全部打包带走, nice! 回到面试,我顺着他的话继续问, c 塔, a t 模式依赖 andou log 表,如果第二阶段执行回滚时, andou log 被误伤了怎么办? tcc 的 try、 confirm、 cancel 三个阶段,如果 confirm 阶段超时或失败了,你怎么处理?业务上允许人工介入吗?如果 a 库扣款成功, b 库加款失败,但此时 c t 协调器也挂了,你怎么保证最终一致性?你有没有考虑过基于本地消息表或事务消息的方案?他们的优缺点是什么?你能画一下你设计的方案的持续图,并标出每个阶段可能失败的点和补偿措施吗?他瞬间慌了,只知悟半天,只说项目中用的是 c t 框架,都封装好了,没仔细想过底层原理, 也没遇到过协调器崩溃的情况。面试到这里基本就可以结束了。这正是会调用框架和能设计可靠分布式事务的核心分水岭。 很多人以为引入一个分布式数框架就解决了问题,却忽略了任何框架都有边界和异常场景,真正需要的是理解一致性模型和补偿设计。面试官问这个问题,考察的不是你会不会配置 c 档,而是你能不能在没有框架或框架失效的情况下, 独立设计出最终一致性的解决方案。真正能通过面试的分布式事物设计,以跨库转账为例,必须吃透三层核心逻辑。第一层,先明确一致性要求和可选的实现模式, 不是所有业务都需要强一致,先区分场景强一致。两阶段提交 c t r t 模式,最终一致 t c c 本地消息表 rocket m q 事务消息 cyg。 以跨行转账为例,通常选最终一致性,因为跨行汇款本身就有延迟。 第二层,选一种模式落地核心流程,以本地消息表加定时对账为例,步骤一, a 库开启事务货款金额,同时写入一条本地消息表。步骤二,定时任务扫描,待发送消息投递到 m q。 步骤三, b 库消费 m q 消息执行加款成功后,回调更新消息状态为已完成。步骤四,每天对账扫描长时间未完成的消息, 人工核自动补偿,面试时能画出实图,并标出 a 库事务边界 m q 投递失败重试 b 库密等处理就是高分。第三层,生产落地的异常处理细节异密等信, b 库加款必须做密等,防 m q 重复消费,用唯一事物 id 去重。 二、消息表清理定期规章,已完成消息,避免表过大。三、对账补偿兜抵任务扫描超市未完成消息触发重试或告警,支持人工修复。四、监控监控消息表积压量补偿任务执行情况讲到这里大家就明白了,面试官问,分布式事务根本不是考你会不会用 c 一 太核心,考察三点, 能不能区分强一致和最终一致的适用场景,知不知道不依赖外部框架如何实现最终一致性?有没有密等补偿对账等生产落地经验?普通后端依赖框架,框架崩了,业务就崩大厂后端能徒手设计一套最终一致性方案,扛得住异常经得起对账。你呀,总是能给我出点新花样。

你说你做过分布式系统,那我问你,跨库转账场景下,如何保证分布式事务的最终一致性?刚面了一个四年经验的后端,我问他,以跨银行账户转账为例, a 库扣款, b 库加款,从流程设计到异常处理,再到最终一致性保障,你怎么在工程上落地? 他想都没想就说用 cata 的 at 模式或者 tcc 框架会自动回滚,保证两个库要么都成功,要么都失败。我顺着他的话继续问, c t r t 模式依赖 android log 表,如果第二阶段执行回滚时, android log 被误删了怎么办? t c c 的 try、 confirm、 cancel 三个阶段,如果 confirm 阶段超时或失败了,你怎么处理? 业务上允许人工介入吗?如果 a 库扣款成功, b 库加款失败,但此时 c t 协调器也挂了, 你怎么保证最终一致性?你有没有考虑过基于本地消息表或事务消息的方案?他们的优缺点是什么?你能画一下你设计的方案的持续图,并标出每个阶段可能失败的点和补偿措施吗?他瞬间慌了,吱吱呜呜半天,只说项目中用的是 c 塔,框架都封装好了, 没仔细想过底层原理,也没遇到过协调器崩溃的情况。面试到这里,基本就可以结束了。这正是会调用框架和能设计可靠分布式事物的核心分水岭。很多人以为引入一个分布式 事物框架就解决了问题,却忽略了任何框架都有边界和异常场景,真正需要的是理解一致性模型和补偿设计。 面试官问这个问题考察的不是你会不会配置 cita, 而是你能不能在没有框架或框架失效的情况下,独立设计出最终一致性的解决方案。真正能通过面试的分布式事物设计, 以跨酷转账为例,必须吃透三层核心逻辑。如果这道题目你也不会回答的话,我整理了让大厂 hr 沉默的必考题库,包含 jvm 夺命连环问、 spring 灵魂八谷高并发必杀场景、 readis 深度陷阱点个赞, 评论区甩六六六,打包带走 nice 第一层,先明确一致,先区分场景 强一致两阶段提交 cata a t 模式,最终一致 tcc 本地消息表 rocket milk q 事务消息 s a g a 以跨行转账为例,通常选最终一致性,因为跨行汇款本身就有延迟。第二层,选一种模式落地。核心流程, 以本地消息表加定时对账为例,步骤一, a 库开启事务扣款金额,同时写入一条本地消息表。 步骤二,定时任务扫描,待发送消息投递到 m q。 步骤三,避库消费, m q 消息执行加款成功后,回调更新消息状态为已完成。 步骤四,每天对账扫描长时间未完成的消息,人工或自动补偿,面试时能画出持续图,并标出 a 库事务边界 m q 投递失败重试 b 库密等处理就是高分。第三层,生产落地的异常处理细节一,密等性, b 库加款必须作密等,防 m p o 重复消费,用唯一事物 id 去重。二、消息表清理定期规章,已完成消息,避免表过大。三、对账补偿兜底任务扫描超时,未完成消息触发重试或告警,支持人工修复。 四、监控监控消息表积压量补偿任务执行情况牛逼牛逼!讲到这里大家明白了,面试官问,分布式事务根本不是考你会不会用 c 塔核心考察三点,一、 能不能区分强一致和最终一致的适用场景。二、知不知道不依赖外部框架如何实现最终一致性? 三、有没有密等补偿对账等生产落地经验。普通后端依赖框架,框架崩了,业务就崩,大厂后端能徒手设计一套最终一致性方案,扛得住异常经得起对账啊,这个就叫专业。

要想不被淘汰,就得不断地学习。对于 cata 的 安装涉及到这几个配置文件,下面我们一起来操作一下。首先进入 get 哈普的官网,找到 cata 这个项目,点击进去 这里,然后找到这个按钮点过去,那么这里就有 c 它的各个版本,这里选择的是二点零点零这个版本,那么这里我们选择的是这个 tikat, 点击 z 这个压缩包,把它下载下来,上传到自己的服务器上, 上传到自己服务器上,它的样子是这样的,然后这里我们就使用 t a, r, x, y, f 那 把这个压缩包解压完成之后,它就变成这样子,然后进入 c 它这个目录, 那么进来之后,大家可以看一下这里它这几个目录需要认识一下。首先是这个 b 目录,它里面放着启动程序, 另一个需要关注的就是这个 config, 它里面放的是配置文件,另外就是这一个目录,它放了出式化的 cq, 首先我们到这一个目录去看一下出式化的 cq, 那 么这里大家可以根据自己使用的数据库,把它的出式化的 cq 导入到自己的数据库中就可以。剩下另一个需要关注的就是它这个配置文件,然后我们进来看一下, 刚解压进来的时候,这个文件是没有的,那么我们可以自己创建一个这个配置文件里面的内容配置好之后,那么我们就可以启动 c 塔,返回上个目录, 进入并目录下面了,那么这里它一共有这几个启动文件,这个是在 windows 下面的启动程序,如果你使用的是 linux, 那 么我们启动这个文件就可以,那么这里点, 那么这样就可以启动,如果它屏幕上没有报错,那么说明你的 c 叉就启动成功,那么这里大家也可以使用 ps 杠 e f。 再来看,如果它这里有这个 cata 的 进程,那么也说明 cata 是 启动成功的,那么这里配置完成之后,接下来就要去 nex 的 配置中心来添加这几个文件。首先是 cata server 的 配置文件,它里面的内容是这样的, 那么在这个文件里面大家需要去改成自己的数据库,然后把密码也改成对应的就可以。这个文件配置完成之后,还有一个微服务连接塞塔的配置文件,也就是这个它里面的内容是这样的,里边的内容也比较简单,就是它的事物组,然后是奈克斯的连接地址。 以上三个文件都配置完成之后,那么我们就要到自己的微服务里面来,把这个 c 塔的公共配置文件加载到需要使用的服务里面去。当你把以上的步骤都配置完成之后,我们就可以启动微服务, 那么大家在使用 c 塔的时候其实也很简单,你只要加上一个注解就可以,只要在对应的方法上加上这个注解就可以,如果其中某个服务发生错误,那么整个事物都会进行回滚。

最近我在做 seed 的升级改造,然后在做的过程中间呢发现了一些问题,所以今天来给大家 呃分享一下吧。呃,问题是这样子的,比如说我们的微服里面呢,我们既会去用到 c, 他也会去呃用到下一点 gdp c, 那么如果说我们下顶我们配了主重的话,可能就算我们主库和重库用的是同一个数据库,其实也会有问题。呃,这是原因呢,就是我这个视频要讲的,那我来分析一下, 比如说我现在直接启动我们的呃看胸膜应用,那么在我应用里面呢,我到时候会来请求我们这个摄影师,这个摄影师呢,他其实就会去开启一个全局失误嘛,但是我在最后我却抛了一个控制针,所以说讲道理呢, 呃,相当于这个全局事务只有一个分支事务,那么我这里跑了异常的话呢,就会导致这个全局事务,也就是说这个分支事务应该是要回滚的啊,这应该也是 c 他,他正常来说他也是能够支持的, 但是就是因为我用的虾顶 gdpc 之后啊,像他就分支事物就会回滚失败。我们来试一下,比如说我来访问这个泰式的 啊,比如说我们看日志的话呢,确实是开启了一个拳击事物,并且呢这里也会开始去回滚我们的分支事物,但是很明显他一直没有成功啊,我们稍微等一会, 好,我们发现呢,等了很久,他确实 就一直卡在这里呢,也没有什么日志,他等一下应该是会抛一段日出来的。所以从这个现象啊,这里抛了一个控制针啊,这这个控制针是我们自己抛的,但是在最后呢,他又继续去回滚了,所以相当于他肯定是前面分支事物。 呃,他就一直是没有回滚成功的,那原因在哪里呢啊?其实我真正自己在排查的时候呢,也是排查了一段时间的 啊,最终呢是从数据库这一边找到了一些。呃,切入口吧,比如说我去查看当前有哪些进程啊,但我们可以多查几次啊,因为他他有的在做一些别的,比如说我们发现 像这个 delete, 它其实是执行了,呃,挺长时间的,你看它就一直,其实一个 delete 来说,它应该是能够执行很快的,我这里面其实就一两条数据,所以它为什么一直在这里卡住了呢?它为什么一 一直就没有执行完呢?啊?从我们秀 processes 的我们是看不出来什么现象的,我们直接来执行。呃,这个语句吧,就是直接查看印度 dv 里面所相关的信息。好,我们一执行我会发现,哎,确实还是刚刚这个 delete 啊,他应该是在等待锁啊。那么这些字段呢,我大家可以说一下,比如说啊,这个是哪个对应的哪个表?这个是 锁的类型,是行锁,对吧?然后这些呢,就是跟这个社会有关的,表示是当前哪个失误在等待这把锁,那么这把锁到底是被谁占用了呢?哎,这里就显示出来了,比如说这个 pid, 就表示是买手里面的这个进程,他占用的当前这把锁,那么四七九,我们就可以直接再根据这个四七九去查这个表就可以。 你查到当前这个进程里面的线程啊,只有一个就是五幺九,我们再根据这个五幺九去看这个线程,他到底在干嘛?哎,我们发现 通过这个验证我们可以发现啊,他是根据这个英文的 id 来就可以了。九嘛,那他是查查这个,然后查这里,反正就是一系列的信息,但是我们发现这里就跟我们的 myatt 有关系,并且这里用的呢 for update, 所以从这里我们大概就能够看出来,他确实啊,好像是由于这个 circle 他先发布 data 了,所以说就去加了锁, 从而呢就导致我们这里的 delete, 因为 id 都等于二嘛, delete, 它在 delete 的时候呢,它就一直加不到锁,所以它就一直主设在这个地方,所以,呃我当我们这里只是看到了表面的原因。那为什么呃 呃要去加那个 forthat 呢?对,我们的业务逻辑里面,我们一开始是插入 anti 里嘛,那你要回滚的话呢?啊就是迪丽特,所以说从这里我们也可以放心。确实呢,迪丽特是正常的,也是表示在进行分支事物的回滚,但是就是一直回滚不了嘛, 那呃 insect 也好,呃我们的 delete 也好,这都是我们能够理解的。那为什么这里还实现了一个 select 的 for update 呢? 这就是问题所在。那么这里呢,就需要去分析一下我们 c 塔的原理啊。我这边呢也可以给大家呃大概看一下他对应的源码啊,其实就在呃这一块给大家找一下 啊,就在这里啊,比如说在真正进行分支事物回滚的时候啊,比如说这里这个方法是在最外 外层调过来的昂度,昂度调过来的昂度调过来之后呢,他就会继续执行,就会执行到这个方法。而真正在进行分支事务回滚的时候,或者说在一开始的时候呢,会进行一个验证,呃,比如说会去查询我们通常说的 呃,就 be for image, 哎,包括 of the image 啊,我这里举一个例子啊,比如说在我们用 seed 的时候,我现在假设有一个这段 a, 我本来呢 a 是等于一的,然后我的业务逻辑里面呢,我就把 a 改成了二,好,那现在我这个分支式我肯定要回滚啊,正常来说呢,我肯定就是 把二又修改为一嘛啊,所以说这里的 b for 就是 ef 的,就是二,好。那么但是呢,我在呃回滚的时候,我可能就需要去判断一下,如果说我发现当前的 a 就是已经变成了三,那其实是有问题的。 就是说我分支事务提交之后,然后在全局事务回滚的时,中间这段时间啊,已经有其他的事务把我的那个 a 给改掉了。所以说我们分支事务在回滚的时候呢,我就要去查当前的 这个数据到底是什么样子的。然后我可能就需要去比较一下你当前的数据啊,应该在下面就是这里会去查当前的数据,当前的 record, 然后再和我们的 after record 去进行比较,就是当前表里面的数据和我前面记录的 那个数据是不是是相等的,如果不相等,那就表示是被改了的,那我就不能回滚了啊,别,就比如说被改成了三,那我就不能把三直接改为一,我正常来说是应该要把二改为一的,现在你是三了,那我就不能回滚了,就说这里就需要去查 当前的数据,并且你想嘛,查出来之后,那你你你这里还下面还有逻辑啊,那么我在执行这些逻辑的时候呢,你肯定也不能让其他事物去把你 a 字段去进行修改,所以说他在执行 这个查询的时候呢,就会用到 for update 啊,这里呢,我可能就一时半会就不带。呃,就这里,对,就是去查,并且运用到了 for update 就加锁,加了锁之后我就把当前的数据查出来,然后再和 up 的一面积进行比较,如果说发现两者一致,那么我才会去真正进行回滚。 而我们这里的回文呢,其实就是迪丽塔嘛,就是去执行迪丽的操作,所以这就是一个正常的 c 塔的分支事物,他回滚的逻辑就是先查并且发布的,查出来之后就进行比较比较,如果发现数据没有改变,我就去迪丽特, 就是删除掉我前面插入的那条数据。好,这是正常的,似乎是没有什么问题的,但为什么到我们这里就有问题呢?啊?就这个就跟我们瞎点 gdp c, 他确确实实就是有关系的,因为在不管是 c 他也好,还是瞎点 gdp c 也好,他们都会有各自的 呃 data source 啊,比如说 c 场里面,它叫做 data source proxy, 然后相对于 t v s 里面,如果说我们用的组成就是 master slave data 硕士,如果我们单独用他们两个的话呢,他们两个都会去代理,比如说德鲁伊的 data 硕士,或者说其他的更底层的 data 硕士。但是如果说我们 呃在一起使用的话,就会是 ceta 的去代理,下面一个 d b c 的就是 ceta 的这个作词,下面是 mas 的 snave 的作词,然后再下面才是德鲁伊的,这个是呃的 c 的硕士,那么这就会有问题,比如说呃 c 塔嘛, c 塔上现在需要去执行 c 口,那肯定就得去建立连接,那么它一建立连接呢?其实最终就就是利用的我们相连 g、 d、 b、 c 去建立数据会连接,而我这个 master snap 的硕士,它最终就 就建立出来,就是 mass 的 sniver connect 型,这个数据会连接,最终 c, 他其实用的是这个连接,而这个连接他在执行社会的时候,他就根据当前要执行的社会来判断。比如说你执行的如果说是 select, 那我就会和 重库去建立数据库连接,如果说你执行的是 inside 这些,那么他就会和主库去建立数据库连接,那这就不就有问题了吗?就是我分支数在回滚的时候,我一开始是查询嘛,对,这个时候我获取的其实是重库的数据库连接好,然后获取完之后呢,你 就继续去 delete, 而 delete 的时候,你又获取的是主库的数据会连接,就变成了两个连接,而前面这个连接它并没有提交,因为按照 c 塔正常的逻辑来说,它应该在 delete 之后才才去提交的。 说对于前面这个事物而言,他加了锁,但是呢锁又一直没有释放,而后面这个事物他想要 delete 的时候呢,他就想要去加锁,但是又加不到锁,因为他们不是同一个数据库连接,更加不是同一个事物,所以后面这个事物他加不到锁,从而就卡住了, 从而就导致我们分子事物就回滚不成功,所以这是呃最根本的原因,所以,呃,就如果说我们要解决这个问题的话呢?啊,就当我们可以扩展的。先想一下,就是对于斯伊塔的这个呃呃数据员而言, 那大家说的是 proxy 而言,他就建议不要去代理相连接的 b c 的,因为你一旦代理了,那么就可能会导致 c 塔内部他在执行一些逻辑的时候,他可能原本要执行很多很多 ceo 嘛,这些 ceo 呢,原本是要在一个事物里面去执行的, 但是如果说你是 c 塔代理的相连接 dbc, 那么很有可能就导致这多个操作被分散到多个数据库连接中间去了,那很有可能就会有问题,对不对?所以我们改造的方式呢,也就是去 呃就换一个顺序,让虾顶的去代理 cat 的啊,最终呢,其实是没有探到问题的,包括虾顶内部,他后面也支持 cat, 他也是这么做的,所以,呃,这是这个问题的解决方式,但具体是怎么改的,我这个视频可能就不太方便继续上台去讲了,后面再分析 啊。然后这里顺便提一准,就如果说我们,嗯,前面我们说组成是同一个库吗?或那就算你组成是不同的数据库,其实也可能也会有问题。比如说 c 塔,它提交分支事务的时候会插入 on the log, 这个时候插入肯定是主库, 但是在回滚的时候呢,他需要去查出 undolog 嘛,然后查 off 的 emai 加 e 呃 b for email 家会查安 dolog, 而查的时候是重库,所以如果你储存延迟比较大的话,那很有可能就查不到,那不照样会 会很失败吗?所以这也是问题,所以呢这是,呃,就还是前面说的,就如果说 c 塔整合下定决定 d b c 的时候呢?你可能需要自己做一些改造。好,所以这是就今天给大家分享一下我的这一块的理解吧。

一位五年经验面阿里 p 七面试,他说前面聊 jvm 和 reddit 都很顺,结果在分布式事务这一块翻车了。面试官问了一个经典的微服务数据一致性问题,用户下单场景涉及三个服务,订单服务、积分服务、优惠券服务。假设积分扣了,优惠券消了,但最后一步订单创建失败,此时积分和优惠券怎么回?滚? 你项目里用的什么方案?为什么选他?他自信回答,我们用 cata 的 a t 模式加个注解就行。面试官追问, cata a t 模式在一阶段释放本地锁后,如果有其他县城来读数据,会不会读到脏数据?如果积分服务是第三方接口, tcc 还能用吗?沙卡模式的密等性怎么保证?他当场哑火,假如这道题目你也不会回答的话, 我整理了让大厂 hr 沉默的必考题目八,股文和场景题都有,扣 pdf 就 拿走。 分布式事务是微服务架构中最难啃的骨头,今天就带大家拆解这几个主流方案,告诉你什么时候该用傻瓜式的西塔,什么时候必须上硬核的 tcc, 以及何时无奈选择 saga。 一 场景复现,微服务下的数据分裂,在单体应用时代,这根本不是问题。一个 a transactional 处理利用数据库本地事务,要么全成,要么全败。但在微服务架构下,数据库是物理隔离的,订单服务连接 order db, 优惠券服务连接 coupon 下滑线 db。 惨案发生, 积分扣减成功,优惠券核销成功,订单插入失败,结果用户的积分和券没了,订单却没生成。 这就是典型的分布式事务问题。二、方案 a cata 开发者的后悔药 cata 是 阿里开源的分布式事务框架,其中 a t。 模式是最受欢迎的,因为它是无侵入的。一、代码失利,傻瓜式开发,你只需要在发起选举。傻瓜式开发,你只需要在发起选举。 l 注解二,致命死穴藏毒于权局所 cata a t 为了性能,在一阶段就释放了本地数据库锁写隔离。 cata 通过全局锁防止脏写读隔离,因为本地锁已释放,其他没有加 cata 注解的普通事物会读到一阶段已经修改但全局并未提交的数据。 三、方案 b, tcc 高病发下的特种兵,如果你的业务是电商核心交易列表,必须请出 tcc。 一、 核心原理与代码资源预留。 tcc 不 依赖数据库事务,而是把业务拆分成三个阶段,你需要在接口定义上明确这三个方法。 二,隐形成本 scam 侵入面试官问你成本,别只说写代码类,最大的痛点是 dba 想打你,你必须改造业务表给积分表加 frozen 字段,给库存表加 frozen stock 字段。如果是老系统,改表结构风险极大。四、方案 c, saga 模式, 第三方服务的无奈之选面试官绝杀题,如果积分服务是第三方 sas 或者是银行接口,你根本改不了数据库,怎么搞 tcc? 答案, tcc 搞不定,只能用 saga 原理,没有预留阶段,直接干正向操作,直接调用银行扣款接口补偿操作,如果后续失败,调用银行退款接口进行补偿。密等性。 saga 模式下,由于网络可能超时,正向操作和补偿操作都必须支持密等, 否则重试时可能导致多次扣款或多次退款。五、终极对比,一张图看懂选型,面试时直接画出这张表,绝对加分。 面试官问选哪个,其实是在考你的架构权衡能力,请记住这个决策漏斗。一、资产增加,选 m q, 允许延迟溢步性能最好。 二、资产扣减,选 t c c 强一致,抗病发,虽然要改表结构,但为了资金安全值得。三、资产扣减,选 sata a t 无法改表结构,只能靠补偿。四、后台非核心业务,选 cata a t 开发效率优先。六、 tcc 落地的三大地狱坑如果你选了 tcc, 面试官一定会问这三个词儿答不上来,说明你没做过一、空回滚现象, try 请求丢包没执行, tc 就 发起了 cancel 解法,事务控制表 cancel 执行前查不到 try 记录,直接返回成功。二、悬挂现象,网络拥堵, cancel 比 try 先到, try 到了之后如果不拦住,资金就被永久冻结了。 解法,初二执行时查事务表发现已有 cancel 记录,直接拒绝三密等现象,网络抖动, confirm cancel 被重试多次。解法,基于局局部事物 id 做唯一缩影校验。七、写在最后,分布式事物没有银弹 c t a t 是 给开发人员的糖 t c c 是 给架构师的药, saga 是 无奈的拐杖 技术没有高下之分,只有场景之别能说清楚这三者的边界。 p t offer 就 在你手中, nice!

你说你懂渣吧后端那局异常处理该怎么设计才不被人骂?最近面试了一个后端工程师,我问项目里如何统一处理运行时异常和业务异常,他说直接 try catch 吞掉,然后返回 new 就 行了, 我当时血压就上来了,我追问什么时候抛 check 异常,什么时候用 unchecked 自定义业务异常怎么写? 异常练怎么保留根音?如何避免几十个 catch 块堆成屎山?不,场景下异常被吞了导致不回滚怎么办?假如这道题你也不会回答的话,我整理了让大厂 hr 沉默的必考题库,包含高频八股文、实战场景题、大厂简历等。只要是我粉丝点个赞,留下七七七打包带走。 那么这道题该如何回答才能让面试官哑口无言?接下来带大家一一解析。 java 后端异常处理必须遵循 顶层兜底加业务精准加日制完整加事务感知。方案一,定义统一异常处理器使用 add controller advice 加 add exception handler 全局处理,区分业务异常和系统异常。方案二,设计自定义异常体系 based business exception 加具体此类,避免抛出 exception 或 to follow 这种上帝类型。方案三,事务中严禁抛出除外,否则事务不回滚。 如需捕获,手动调用 transaction aspect support current transaction status there set rollback only。 方案四,异常日制与响应分离异常只记录在 log 点 error 中,返回给前端的必须是试图 jason 对 象,决不能直接输出堆栈。方案五,善用 try with courses 和 finally 释放资源,不用手写 final 里盼空关闭异常也要单独 catch, 避免掩盖主异常 一个核心原则,异常处理的本质不是防崩溃,而是可追踪可降级。项目里到处 catch 后返回 no, 最终线上问题无从查起,这就是烂代码的味道。这道题考的是 java 后端工程化落地能力,异常处理直接决定线上排查效率与系统见状性。 最后问一下,你们项目里遇到掉坑里的异常一般是怎么处理的?是甩锅给框架还是自己埋雷?一起来聊一聊。

时钟回滚导致事务 id 重复,都给我回来好好看着,别下次面试官问你。哑口无言。面试官, cata 一 点四模式是根据时间戳生成的事务 id, 那 时钟回滚了是怎么保证不重复的? 你当场吱吱呜呜。每次生成全区事务 id 都和之前生成的比较,如果比之前大才允许生成,以对号性能不说,那时钟回滚期间服务器直接罢工。 c r d 一 点四后事务 id 生成优化你懂吗?重点来了,彻底解决时钟回滚加性能瓶颈。 c r d 一 点四加优化,记住这三点,面试直接满分!答, 一,节点 id 占高位,不同机器天然不重复。二,压根不用怕多机器冲突机器标识,一锁死跨机 id 直接绝缘,按 automeglon 纯内存自增,彻底抛弃系统时钟,依赖时钟回滚随便滚。我生成 id 不 看你系统时间内存自增就完事。唯一性稳如老狗。 三,序列号一出,直接超前消费,下一秒老雪花算法每毫秒只能生成四零九十六个,不够用。 snowflake 直接推进时间戳,借用下一毫秒序列空间并发上线,直接拉满。屏幕前的杠精忍不住了,一直超前消费,重启不就重复了? 拜托别傻了,要重复的。 qps 冲到四百万加秒, sita 的 tc 早就崩了,轮不到 id 出问题。最后背会这句就完事了。 zita 一 点四加节点 id 放置高位锁机器防跨机重复,只依靠服务器开始时刻,时间戳绑定序列号内存自增,高性能加全区唯一加,防止时钟回滚,完美解决分布式 id 所有痛点。面试还被问过哪些分布式坑?评论区打出来,下期带你拆解!

有个四年经验的朋友找我复盘美团三面,本以为是稳拿 offer 的 技术交流,结果他开口第一句话就是,我被降维打击了。他说前面聊的都挺顺,面试官一直点头,直到聊到分布式事务。这哥们觉得稳操胜券,把西塔 a t 模式的二阶段提交回滚日制全局所原理背的滚瓜烂熟。 结果面试官听完压根没问原理,直接反手掏出一个真实的支付结算场景,如果在核心账务系统 qps 达到五万,你敢用 a t 模式吗? 如果全局所在高病发下排队超过五秒,导致下游网关全部超时重试,由此产生的千万级资金对不齐的资损,你负责还是我负责?那一刻,这哥们说他手心全是汗,吱吱呜呜答不上来。假如这道题你也不知道怎么回答的话, 我整理了让面试官沉默的大场必考题库,包含 gvm 夺命连环问、 spring、 灵魂八谷、高病发必杀场景、 radis 深度陷阱,留个六六六直接暴走。这就是大场面试最毒辣的地方,只会用工具是不够的,你得懂选型背后的生死线。 一、推翻误区, cata a t 模式不是万能灵药。很多程序员有个错觉, cata 出现后,分布式事务就成了一把缩,只要加个 ad global transaction, 万事大吉。但是 a t 模式的本质是代理数据源加全局锁, 在低病发的管理后台,它确实香。但在大促秒杀支付这种核心链路上, a t 模式有两大死穴,一、性能黑洞。每一个血操作都要去拿全局锁。在高病发场景下,数据库连接会被瞬间卡死,引发全链路血崩。二、数据脏血。 如果某个非事务链路偷偷改了数据, a t 模式的回滚迹象会直接失效,导致数据彻底崩盘。结论,在支付核心账务中心,严禁无脑使用 a t 模式。二、美团选型标准分布式事务。三、剑客,面对不同的业务深度,大厂有一套极其严格的选型天平。一、 强一致性短事务场景 t c c 模式,这是大厂核心业务的特种兵。核心逻辑, try confirm cancel 为什么选它? 它是应用层枷锁,性能极高,没有数据库。长事务锁,适合高并发核心场景,强制规范落地。 tcc 必须实现密等性空回滚,防悬挂少一个都不行。二、最终一致性长事务场景 saga 本地消息表,对于流程长、跨部门多的业务等不起。 tcc 核心逻辑,每一个步骤成功后发送异步消息,下游消费补偿为什么选它?无锁设计系统吞吐量巨大, 强制规范,必须有完善的重试机制和人工干预兜底,保证数据最终一定能对齐。三、低并发,简单跨库场景 cata a t 模式,适用场景,内部管理系统。低并发业务,追求开发效率,核心优势,零侵入,落地快,降低开发成本。三、面试满分答题模板,建议收藏 当面试官问你,你们分布式事物怎么选型?请按这个四步走一、聊本质。首先,分布式事物是 cap 定律中 a 与 c 的 权衡,没有万能方案,只有场景适配的最优解。二、嗅对比,讲清楚 tcc 的 极致性能, saga 的 异步接口以及 at 模式在高病发下的所冲突风险,重点突出你对资损的风险意识。 三摆标准,给出上述大厂选型标准,支付核心用 tcc, 长流程用消息补偿后台用 a t。 四谈实战,我们在落地 tcc 时,专门通过状态机解决了空回滚问题,同时全链路建立了分中级数据对账系统,确保在极端网络分区下也能做到零资损。 nice。