视频知识库
首页
  • 暧昧拉扯
  • 暧昧撩人短句
  • 安全
  • 安慰陪伴
  • 表白深情
  • 产品复盘
  • 成长思考
  • 存在意义感悟
  • 打情骂俏技巧
  • 待归类
  • 道歉认错
  • 复盘与精进
  • 搞笑娱乐
  • 告白文案
  • 个人目标
  • 沟通技巧
  • 哄人
  • 技术
  • 健康
  • 接话技巧
  • 开场破冰话术
  • 拉扯博弈
  • 恋爱相处
  • 两性情感
  • 撩人话术
  • 聊天话题
  • 聊天心法
  • 矛盾化解
  • 品德修养
  • 亲子家庭思考
  • 情绪内耗
  • 商业认知
  • 社交原则
  • 深情短句合集
  • 识人避坑
  • 送命题化解
  • 投资理财
  • 网络用语
  • 吸引推进
  • 相处感悟
  • 向上管理汇报
  • 心理学
  • 原生家庭
  • 职场
  • 职场方法论
  • 职场情商法则
  • 追求脱单
  • 自我成长
  • 自我姿态边界
  • AI工具
首页
  • 暧昧拉扯
  • 暧昧撩人短句
  • 安全
  • 安慰陪伴
  • 表白深情
  • 产品复盘
  • 成长思考
  • 存在意义感悟
  • 打情骂俏技巧
  • 待归类
  • 道歉认错
  • 复盘与精进
  • 搞笑娱乐
  • 告白文案
  • 个人目标
  • 沟通技巧
  • 哄人
  • 技术
  • 健康
  • 接话技巧
  • 开场破冰话术
  • 拉扯博弈
  • 恋爱相处
  • 两性情感
  • 撩人话术
  • 聊天话题
  • 聊天心法
  • 矛盾化解
  • 品德修养
  • 亲子家庭思考
  • 情绪内耗
  • 商业认知
  • 社交原则
  • 深情短句合集
  • 识人避坑
  • 送命题化解
  • 投资理财
  • 网络用语
  • 吸引推进
  • 相处感悟
  • 向上管理汇报
  • 心理学
  • 原生家庭
  • 职场
  • 职场方法论
  • 职场情商法则
  • 追求脱单
  • 自我成长
  • 自我姿态边界
  • AI工具
  • 笔记分类

    • 暧昧拉扯
    • 暧昧撩人短句
    • 安全
    • 安慰陪伴
    • 表白深情
    • 产品复盘
    • 成长思考
    • 存在意义感悟
    • 打情骂俏技巧
    • 待归类
    • 道歉认错
    • 复盘与精进
    • 搞笑娱乐
    • 告白文案
    • 个人目标
    • 沟通技巧
    • 哄人
    • 技术
    • 健康
    • 接话技巧
    • 开场破冰话术
    • 拉扯博弈
    • 恋爱相处
    • 两性情感
    • 撩人话术
    • 聊天话题
    • 聊天心法
    • 矛盾化解
    • 品德修养
    • 亲子家庭思考
    • 情绪内耗
    • 商业认知
    • 社交原则
    • 深情短句合集
    • 识人避坑
    • 送命题化解
    • 投资理财
    • 网络用语
    • 吸引推进
    • 相处感悟
    • 向上管理汇报
    • 心理学
    • 原生家庭
    • 职场
    • 职场方法论
    • 职场情商法则
    • 追求脱单
    • 自我成长
    • 自我姿态边界
    • AI工具

技术

死磕分布式一致性:面试拿Offer的技术复盘

来源:视频-bilibili | 日期:2026-08-09 平台:bilibili | 标题:【极海】死磕分布式一致性,面试结束直接发Offer了 | 时长:1104 链接:https://b23.tv/DXITnfn 提取时间:2026-08-09T06:33:23.090Z

2026-08-09 14:31:58 CST|18min 23s

Keywords: 缓存、并发、一致性、线程、结算、幂等、权益、事务、数据库、分布式事务、布隆过滤器、定时任务、业务场景、业务链路、订单消息、平台补贴、业务平台、热点数据

Speaker 1 00:00:00.080 还是先简单自我介绍一下。

Speaker 2 00:00:01.680 三年的经验,海外电商平台的商家端的一个系统开发,负责他们的权益中心这块。

Speaker 1 00:00:07.240 现在还在职的吗?对,是的。

Speaker 2 00:00:08.920 为什么考虑换工作呢?个人成长方面的考虑吧,发展到一定地步了吧,一个平行期或者一个下行期,一个下行期吧,那我觉得在这段时间里面比较少有空间可以去再创造更多的价值吧,就其实这几年把很多该做的事情也都做了挺多了,然后也都做得很完善,就从个人责任的角度上,所以选择了跳槽。

Speaker 1 00:00:26.680 那你打算找怎样的工作呢?

Speaker 2 00:00:28.920 目前肯定还是考虑在一线互联网大厂里面的看吧。

Speaker 1 00:00:32.400 你之前哪个项目最有亮点呢?

Speaker 2 00:00:34.120 就是我觉得就我其实我简历上很有写,就是主要这应该是,就是你没有列到第一个项目吧,整个权益中心的一个可以说是它底层的一个平台能力吧。

Speaker 1 00:00:42.560 那你这里面解决了什么问题啊?

Speaker 2 00:00:43.920 核心其实是对一个什么什么东西抽象的,就是它是对一个。卖家活动的一个抽象平台的业务,它像很多会需要有一些活动给卖家来参加,是为了干嘛呢?是一个是给他去做权益的发放,比如说帮助卖家成长啊这样的一个目的,可能平台会希望从中也可以得到一些收益呀,就是相当于我是一个权益中心吧,只不过它承载的业务的一个个抽象是叫做活动,业务平台它主要的一个业务,它可以很方便很快速的去创建一个活动,并且配置说这个活动下面需要给到这些卖家有什么样的一些权益,比如说像给他的广告券也好,给他做补贴也好,或者给他做一些佣金的减免也好,有些活动他也可以选择去收费,相当于我给了你这些好处,那我可能也要收你一定的一些费用,包括像卖家级别去收你的报名费,或者说。每个订单维度的去收你的佣金这种模式,基于这样的一个业务玩法,具体他的业务目的,他可以根据业务方的不同,他可以在这套能力上构建出他自己的一些玩法。

Speaker 1 00:01:41.840 那你说有分布式事务,就做一致性保障方案设计,这个具体是什么业务场景?

Speaker 2 00:01:46.400 他就是像我刚刚说到嘛,就是他这个核心是一个是做。权益的发放,一个是做费用的收取,其实从从这个结构就可以看到它有一个很大的一个分布式事务的点嘛,首先分布式事务它肯定是说我是有两个不同的事务,可以说在不同的机器上。

Speaker 1 00:01:59.500 你能再明确一下这里哪里有分布式事务吗?

Speaker 2 00:02:02.100 权益的发放和费用的收取,权益发出去了,我要收钱,那这一定是个并行的,一个是一是同步的,我不能说我权益给到你东西,但是我钱没收回来。

Speaker 1 00:02:10.660 那你这里怎么去解决的呢?

Speaker 2 00:02:12.180 当时这块其实也是一个一个一个设计设计的点嘛,就我们这个当时我我是有去有调研一下,这有几个分布式事务的一些常见的一些。嗯,思路和解法吧,最后定了一个,我们怎么说呢?可以大概说一下,我们当时在选定这个方案的时候的一些考虑吧。有调研过像像分布式事务,像比较主流的一些解决方案,像比如说 2PC 两阶段的,还有像 TCC 的也看过,其余 track 跟 cancel 的,然后还有像 Zaka 的可靠消息的最终一致性的,我们其实最终定的这个方案是应该是比较偏的,它其实没有那么的教科教科书啊,完全像那个标准的方向,其实更贴近就是像可靠消息最终一致性,这种最大努力的通知的这样的一个方案。

Speaker 2 00:02:54.740 其实每个方案的优缺点大家都有去,当时都有去看,像比如说两阶段的话,那我可能就要需要考虑,打个比方,一个业务场景,比如说我现在我需要从这卖家他的 GMV 账户里面扣 100 块,同时给他的权益是说,诶,在他的广告。余额里面给他充个 200 块钱,如果是继续这种 tob c 的话,他有个问题就是说我会需要在两边的事务都是需要保持一个事务状态,比如说我要调结算,那我需要结算那边他在事务执行完之后他不提交,然后也同样我需要在广告那边,我需要调用他们去进行这个广告券的增加之后,他也不能提交,然后需要我这边。

Speaker 2 00:03:29.000 我作为一个事务的管理者,我就统一调配他们去同时提交来完成这个分布式事务的一个原子性嘛。这个是一个点,那这个点他就会当时是考虑就说一个是资源啊,可能会处理不好,会有死锁的情况,所以说这种情况当时是有这种短板,这个方案是没有怎么太去考虑。然后另外像 TCC 双方案呢,它其实是比较好的去解决这种死锁的问题啊,就是它主要是就基于一个中间态的设计嘛,相当于做 try 的时候,我各自去把各自的资源推到一个中间态,那比如说对结算来说,我就不可能说我这笔钱先冻住,那我最后等我这边作为一个事务管理者的角色,我去统一调配他去推到一个最终状态,要么就是成功过去,要么就是撤销。

Speaker 2 00:04:08.560 这个有个问题就是说。当时广告那边,他们其实对这个中间态是没有这套设计的,就其实这个方案他对这个整个系统侵入性还是比较高,那需要他们自己本身要有这种中间态,或者整个系统设计上需要有支持的这种模式,因为这个点就是也是没有采纳的一个原因吧。像还有像 Seata 这种,它是基于一个这种事务链的方式,它和 TCC 相比就可能是说它不需要我去有一个中间态,一个正向,那大家都做一个正向的事务,然后我要是有问题,我就同时让你们去做个反向的事务。当时我们主要是看,就我们目前的那个场景,它就可以说不太需要有一个反向的一个动作吧,就我们更多还是希望让我去正向扣,扣完了就尽量都都去扣完。

Speaker 2 00:04:46.650 不希望有一个逆向的一个动作出现,比如说我另外一边没有充上,那我需要整个回滚,我觉得整个复杂度又太高了,而且我们也其实本质原因还是对相对来说对这种一致性的要求没那么高,所以就最终我们比较追求的还是一种最终的一致性的方案嘛。卖家在,比如他在签约参加了一个活动,他点这个动作的时候,我们会在一个本地事务里面去把卖家他获得的权益记录,以及他的要去被扣费的一个。这种扣费记录先记在我们本地,相当于这两个是,一个是我同时去落库的,可以保证就说那他参加了,我这里一定有一个权益记录,一定有个扣费记录。

Speaker 2 00:05:23.490 我们再去把这两个记录去转换成消息,我们把它转换成异步的方式,因为他签约之后,他并不想把它做成一个同步的去做这些权益的发放,所以是把它发成一个消息,自产自销这种方式,就相当于权益的发,权益的那个对权益的记录发条消息,另一个监听者,我去监听这条消息,我去做权益发放。

Speaker 2 00:05:41.890 同样的那个扣费的也是这样的逻辑,这样的话我就可以说利用这个 MQ 消息,它的自动自动重试机制,可以有一定的保障,比如失败了它会重试去发。另外我们再会再去加上一个定时任务的扫表。去每天去,相当于再兜一次底,看一下,因为我每条记录会记录他的那个发放状态嘛,比如他扣费有没有成功,他的状态是什么样的,权益发放有没有成功,那这样的话我有个定时任务,我就可以去轮询地去扫表,来确保说,他的确所有的权益和那个扣费都是真的,成功收了,并且成功发了。然后再加上最后,我们再有一个对账,去保证天级别他的是,一定是能够对得齐的。也是整个大概是这样的一个保障措施,在这样一套链路把它做下来。

Speaker 1 00:06:19.240 你刚有一个点啊,就是你本地事务提交之后,怎么把它转成消息?这一步是怎么做的?

Speaker 2 00:06:23.760 存下来之后,其实就直接在存的时候就可以发消息了。

Speaker 1 00:06:26.920 存了,还没有发消息的时候,这个时候机器挂掉了。或者重启了。

Speaker 2 00:06:30.670 那这个时候,就,我们会有一个定时任务去兜嘛,就相当于如果有这种极端情况,那我从来没发出去,那这个时候就靠定时任务去兜了,那他会不会去扫表,看到有这个表,他如果成功发了,那肯定会状态会会变嘛。假如说哪怕消息发出去了,但是结算那边,就我这个展示叫之后调结算,没有成功,那这个时候也是要靠那个定时任务去兜。

Speaker 1 00:06:50.830 那这边有没有什么情况会出现重复消费的情况呢?

Speaker 2 00:06:53.990 那这个东西肯定我们是全部都会做幂等的,包括你做扣费也好,返放也好,就是有做。完全有说服力的,因为消息这东西你肯定必须用重复的去求消息和反是很常见的事情。

Speaker 1 00:07:04.890 那你说一种场景,就是说一种他重复投递的场景。

Speaker 2 00:07:08.410 最简单就是网络原因嘛,就比如说我现在我投递一条消息,那如果说broker,MQ, broker 那边他没有收到,这个 MQ 他发消息,他他这个可靠性的保证,他这边会有一个这种确认的机制,我发送者,我消息发送者在发完之后没有收到这个回复确认成功,那我会去进行重试,那很明显,那如果说 broker 那边 MQ 那边收到了,但是可能某些网网络原因,我这边没有收到那条他回复的这个信号,那我就以为他没收到,那我就重发,那就最最最基本的一种场景,那就。重发了,那就是得重复了。

Speaker 1 00:07:37.170 那接口的幂等性保证一般是怎么做的?

Speaker 2 00:07:39.210 调结算来说吧,需要去做扣费,你是商家嘛,会约定一个幂等键嘛,就相当于我这边会拼出一个幂等键,根据我们这边业务状态,什么卖家 ID 啊,什么国家呀,什么活动的 ID 啊,什么权益的这些东西啊,拼出个幂等键,然后每次调结算的时候都会把这个幂等键发给结算那边。

Speaker 2 00:07:55.610 说实话,这个幂等操作其实本质是在结算那边做的,因为他,他是根据这个幂等键,他去看,诶,那这个幂等的这个键,我有没有做过这个发放,他们其实会存的。那如果他找到说,那我这条幂等键,我再。在结算的数据库,他没有找到。有做扣费的这种记录,那他就进行扣费,那如果有做,那他就会做这个扣费,所以其实幂等这一块是在他那里做的,我们只是指定一个幂等的一个幂等件ID。

Speaker 1 00:08:22.120 那如果存在并发的情况,就那两次投递,投递的非常快,重复投递,导致他那边并发了,两个线程去查都没有处理,都去扣费了,可不可能存在这种情况?

Speaker 2 00:08:32.600 哦,你的意思是说结算他那边并发了,相当于他被并发有两个请求过来,相当于这个并发是结算要处理的,是吧?对。对,但是当然我也可以去想一下他们的方案,这是因为我我这个我就没有没有做,但是我理解他们肯定有会去有这种并发的手段嘛,就比如说我想一下,两个请求并行过来,但是他就只能发一个嘛,这两个肯定只能发一个,那。

Speaker 2 00:08:53.280 最,最基本的,那就是加锁嘛,锁住的这段资源,这段代码里面就同一个幂等 ID 的请求只能进来一个线程,这个进来之后我把它发出去了,那我这个时候数据库记录里面就有这条记录了,最后另一条线程它在,它拿到锁了嘛,它再进来,类似于DCL,就 double check log 的一个思想吧,就它会再去查一次,就相当于它在锁里面,它在锁外面会去查一次,有没有这个记录,有没有被扣费过,然后再加锁,加锁完之后里面再去查一次,那就比如像这种情况,它两个请求接过来说都要扣费,因为它是同时进来的嘛,那所以它第一个 check 肯定就是都能通过嘛。还没有过被记录,这个时候是两个。

Speaker 2 00:09:30.160 线程同时都会去竞争那个锁,第一次 check 之后会加锁,加锁之后这两个线程它会同时竞争这个锁,但是只会有一个线程进去,这个线程进去的时候,这次 check 就肯定也还是没有的嘛,它肯定得再检查一次,就确保我能够感知到上一个线程,上一个进来这个锁的线程,它的动作,就比如上个线程它进来,它已经把扣费操作做了,落了库了,那我第二次检查,那我第二个线程进来的时候,我再查一次,那肯定就我就可以。

Speaker 1 00:09:53.680 那如果说我直接进来就加锁,加锁进来了,成功之后我再判断,这个方案有什么问题吗?

Speaker 2 00:09:59.840 这个方案也可以,这个方案也可以,但是这个有问题就说,你这不就完完全全就完全串行啊,就是它第一个 check 的作用主要就是为了让你一开始就直接加锁的话。好像也行啊,我想想这种情况好像是也可以,他在获得到锁之后进来,他在锁里面去检查,他如果是有这个记录,他就不进行扣费。感觉这样其实从逻辑上来,业务上是有问题的吧,我是觉得。

Speaker 1 00:10:24.450 但是在有些情况下确实要做 double check,那你觉得什么情况下适合用这种 double check?

Speaker 2 00:10:30.250 缓存击穿的一种一种情况吧,他在做那个更新的时候,他确保只有一个线程去更新数据库,那其他线程呢,他去再去 double check 的时候,他可以发现他已经缓存有了,那这个时候他就选择缓存,他是这样的思路,这是一种场景,另外场景就比较常见,就单例嘛,就额还是单例的经经典的写法。

Speaker 1 00:10:49.730 单例用 double check,他。主要是为了防什么呢?

Speaker 2 00:10:53.010 跟我们刚说那个结算场景类似,它就是防止并发的,防止重复创建对象,导致它就不是一个单例了。第一个 check 它主要就是为了,相当于它如果已经建好了,那我第一个 check 的时候,我就直接可以拿到我那个已经创建好的单例对象,我可以多个线程同时去拿这个单例对象,它是不影响的。但如果你在,你没有了第一个check,你直接一进来就加锁,它就全都串行了嘛。但是我刚刚结算的,我们刚刚那个场景,我想了一下,好像没有这种情况,所以好像我刚一想觉得好像的确 check 一次也是 OK 的。

Speaker 1 00:11:21.370 你刚有说到缓存击穿,缓存击穿是什么场景?

Speaker 2 00:11:24.450 它一般是存在像这种有一些热点 key 的一些业务场景下,一个一 key 它是特别高并发的一个访问的,那这个时候突然这个 key 它过期了,或者说怎么了,反正就没了,然后翻不到,那这个时候就很大量的流量,它会全部直接打到数据库,这种场景下就叫做缓存,缓存击穿。

Speaker 1 00:11:41.410 你有什么解决方案吗?

Speaker 2 00:11:42.850 就刚刚说的 double check loss 是一种吧,就是1万个并发进来。他只需要有一个去访问库,把这个库的数据更新到缓存,其他 9999 去访问缓存就够了,这是一种解法。另外的话那就比较简单一点了,比如说那我就干脆这个 key 我就不过期了,那我就长期希望它有效,并且我,但是这样的话你可能要考虑一个点,就是怎么做,做缓存和数据库的一个同步吧,保持它数据的一致性嘛。另外要考虑一个问题。

Speaker 1 00:12:07.310 我们刚已经聊到缓存的一致性啊,跟我们前面聊到分布式事务的一致性,这两个一致性有什么区别吗?

Speaker 2 00:12:13.070 分布式事务的一致性,它主要是保证的,可以是说它本质上来说,不是说这个任务,其实就是你可以认为它就是个事务。只不过它是分布式的,它是散在了不同的一个机器上,所以你要保证它的事务特性,保证它的ACID, ACID 的特性,它本身是讨论这个东西的一致性,是说比如说它的原子性啊,这些一致性,那个什么一致性啊,事务里面的这种特性,那缓存一致性,它更多就数据的一致性,数据库的数据一定要和缓存的数据是要一模一样的,不然的话可能会出现延迟,一些会有一些业务的后果。

Speaker 1 00:12:44.590 那事务里面的一致性是什么意思?

Speaker 2 00:12:46.510 事务里面一致性,我理解它其实更多就说我这个事务操作完,它能够说可以保证我整个数据是对的上的,就比如说我这个花出去 100 块。或者说重新来 100 块,它这个账是对的上,那我两个账户我从 A 转到B,总额它是一致的。它其实是一个很蛮结果性的东西,它其实就是这种一致性,我其实它在那个 ACID 里面,这个一致性的特性是我感觉是比较综合一个独特的一个特性,它基本上是需要靠其他三个特性来共同保证的一个结果。

Speaker 1 00:13:15.370 天级 QPS 并发处理方案设计,这个是解决什么问题?

Speaker 2 00:13:19.170 其实它是个比较比较比较泛的一个概念,并发它其实,比如它会分像读的并发还是写的并发,我其实更多我想说的一个场景,我遇到一个场景,它是一个应该是写并发的一个场景吧,就是。会有个业务,因为我有个平台补贴的一个场景,卖家他获得这个权益,那平台会相当于给他个额度,说我给你这个卖家补贴1万块钱,那这1万块钱是你去用券,就商家他创创建的这个券,他花出去了,被买家花出去了,那商家他承担一部分,平台也会承担一部分,要做这个补贴嘛,相当于就要从他的这个类似于从余额里面扣,他是按订单来走的,那我收到一个订单消息,要补贴出一笔,首先他有并发就肯定是有资源的竞争嘛,那就是他主要竞争就在这个记录上,这一条权益记录,这一条金额,这条余额上的竞争,做这个余额的扣减,就因为他有可能同时会有很多订单,然后同时都要做这个扣减,然后这个时候会发生在这个这个数据库层面的一个。这个是问题场景。

Speaker 1 00:14:15.940 写并发会导致数据不正确吗?还是说性能比较低啊?

Speaker 2 00:14:19.860 当然了,两方面肯定都会有,我们是主要还是解的是那个数据安全的问题吧,就是这个都来扣,肯定不要扣错了。你说的那种性能问题的话,其实用写它肯定会有,我其实当时也有也有提到这个解这个性能问题的方案,就其实这两方面我都可以展开来说一下。写的话就很简单了,写的话其实。对这种情况就是就加锁,说实话这种你要并发写,也只有加锁,也没有别的办法,就是。

Speaker 1 00:14:45.470 并发的是更新同一行数据吗?还是不同的行?

Speaker 2 00:14:48.350 的确到不了一行的量级,没那么大。

Speaker 1 00:14:50.070 你们这个更新是先读出来,然后在那处理里面算,然后再去update,是这么一个操作吗?

Speaker 2 00:14:55.390 对,肯定,就基本都是要这样子的。

Speaker 1 00:14:57.270 在数据库里面加一个类似于,比如说悲观锁啊,或者乐观锁之类的。

Speaker 2 00:15:02.710 这个能解,这个当时也是一个方案,就是。加乐观锁,那乐观锁可能具体就看它的并发的竞争大不大吧,那如果不大,其实我觉得乐观锁也是能解的。

Speaker 1 00:15:10.550 或者直接用悲观锁行。

Speaker 2 00:15:11.950 我用那个分布式锁,它本质也是个悲观锁,只不过是。用了 Redis 去解而已。

Speaker 1 00:15:16.350 为什么最终选择了这么一个方案呢?前面说的那两个方案其实并不依赖 Redis 嘛。

Speaker 2 00:15:21.190 我反正当时我是觉得没有什么太大的区别,是随,就后面说实话就随便选的。

Speaker 1 00:15:25.870 并发读这个有什么优化吗?

Speaker 2 00:15:27.470 那读的话其实说实话,那能想到的也就是缓存,我想想做缓存其实也不太好解,因为它也没什么热点问题,一个是这个说实话, QPS 体量还没有到并发读会有性能问题的。

Speaker 1 00:15:38.270 还是写的流量比较高,读的流量不算大。

Speaker 2 00:15:40.750 对,没有太大的瓶颈在读上,那如果说假设啊,假设你说的有这么个场景,那读的并发很大,那也就两种情况,一种是有热点的读,一种是无热点的,像这种无热点的高并发,你加缓存都很难加,就是你也不能说我把所有的缓存,所有的数据全读到缓存里面,你你全来读缓存,那当然你缓存要是够大,你也能这么做,但是一般也不会这么做,这种无热点的这种。

Speaker 2 00:16:00.160 读并发,我能想到的可能也就是类似于不能过滤器这种,可以说过滤一下额外的请求,但你有其他的,比如说接口的优化啊,或者是一些代码层面的优化啊。你像热点问题就稍微好解一点,那我就可以直接把热点数据直接读缓存,那就是写到缓存里面的,其他读全都读缓存嘛。

Speaker 1 00:16:15.840 不能过滤器它是为了解决什么问题呢?

Speaker 2 00:16:17.760 可以认为不能过滤器它是对你一个整个数据集的一个压缩吧。它相当于有一个很小的空间,把你整个数据库里的数据可以全部存到布隆过滤器里面,这样的话,当有请求过来,那我可以快速通过过滤,布隆过滤器可以知道请求的数在不在我这个水库里。当然它会有些衍生的一些什么解决一些场景,比如说像什么缓存的什么穿透问题啊,这种就不说了,但它的本质其实就是一个过滤作用,一个数据集的压缩作用。

Speaker 1 00:16:42.620 那如果我在布隆过滤器里面要去删除一个元素,这个要怎么做?

Speaker 2 00:16:46.220 目目前的话,其实普通的布隆过滤器是删不了,但是现在现在也有什么技术布隆过滤器,什么布谷鸟啊,当时其实也也有了解过,当时就项目中其实也有用到,有轮子的,就好像就只有普通过滤器,布谷鸟好像没找到现成的轮子,那你要自己写,好像。比较难,所以说你普通的基本上是就是不能删,删不了,那你要是删怎么办?做重建。

Speaker 1 00:17:06.850 我看你还写了复杂上下游链路交互设计,主要是做了些什么事情?

Speaker 2 00:17:12.850 这个主要就体现一下,整个整个业务链路的一些复杂性吧,以及就是说可能你要有多方的一些协调啊,包括其实就比如说。对,主要是突出这个点嘛。就。

Speaker 1 00:17:25.190 嗯,交易跟结算你们是两个工程还是一个工程?两两个。你觉得他们为什么要分成两个工程,而不是放在一个工程里?

Speaker 2 00:17:32.510 就以我对他们的了解啊,就其实我是感觉还是蛮不一样的东西吧,就交易他们其实更多是在处理,像那个下单的流程呐,这些正逆向啊,这些东西,结算更多是像对接一些银行的 API 去做什么打账啊、汇款呐,包括一些费用的一些结算梳理啊,它其实是蛮不一样的两块东西,所以它其实分成两个应用,它从架构上比也是合理的吧。但是你说放在一个应用里面去做,这种东西像系统设计上来说也没有什么对错之分吧,就可能更看具体场景。那如果说。你结算和交易它各自都有特别复杂的业务,你放在一个业务,可能它放在一个应用下,放在一个系统下,太臃肿了,就拆开来做呗,或者说刚好从公司的角度,它有两拨人,它从组织架构的角度角度,它要拆成两个应用来做,那就是这样的吧。


IT老齐899.45】为什么GraphQL与AI编程更加适配

来源:视频-bilibili | 日期:2026-08-14 平台:bilibili | 标题:【IT老齐899.45】为什么GraphQL与AI编程更加适配 | 时长:1063 链接:https://b23.tv/42CtwqF 提取时间:2026-08-14T16:38:53.715Z

2026-08-15 00:37:51 CST|17min 42s

Keywords: 后端、脚本、前端、订单、编程、报文、格式、自定义、结构、序列化、强类型、时间戳、反序列化、数据类型、用户对象

Speaker 1 00:00:00.160 说人话,重实战,讲干货。你好,欢迎来到 IT 老齐的架构 900 讲,我是你们的 IT 私人顾问老齐。到现在我已经录制了十多门与编程架构的最新课程,同时还会提供简历优化、模拟面试、 Offer 选择、课程指导、工作建议等多种服务,只要我有经验的事情,一定坦诚相待。有兴趣的小伙伴可以看一下评论区。今天呢,我们来说一个在 AI 编程非常非常有用的东西。以前我们在进行接口开发的时候,默认呢,现在都使用 MVC 中的 Controller 来通过 RESTful 的方式来对外暴露。那现在呢,经过我们三个月和朋友们不断的去验证,发现 GraphQL 在 AI 编程的背景下,有着更多的优势,我们现在已经彻底转向了 GraphQL 的开发模式了。那究竟为什么 GraphQL 会更适合 AI 编程呢?我们来聊一聊。

Speaker 1 00:00:49.790 好的,老规矩,我们先来演示,看一下这个 GraphQL 从表现上和我们传统的 RESTful 有什么样的区别。此时呢,我们弹出来对应的网络面板,每操作一步,我们观察下边的变化。当前做的是一个前后端的分离的工程,我们前端在发送的时候,向后端呢去查询接口。但是大家请注意看,刚才我点击刷新以后,在下方它提交的地址并不是一个自定义的,而是一个名为 GraphQL 的接口。

Speaker 1 00:01:20.950 在提交的主体的部分中,也不是一个咱们说随意写的自定义的,而是一种标准的结构,它包含了三项,分别是 operation name,也就是具体的行为的名称,以及我们要执行的查询什么样的动作,以及它的参数是什么样子,还有呢,额外的一些变量的信息。这便是从前端向后端提交的。

Speaker 1 00:01:45.910 报文的信息了。那现在我们比如说来删除一个订单,当我点击删除了以后,提示确定后,你会发现在这里呢,它会还发送的请求呢是GraphQL,只不过在出现的 operation name 中,它变成了 delete order,删除订单。然后在下面的话提供了关于删除订单的各种细节。

Speaker 1 00:02:09.310 我们现在看到的这类脚本呢,就是 GraphQL 的一种标准形式。它和我们 RESTful 最大的从观感上的区别便是, RESTful 你是一个接口干一件事,完全都是自定义的。而 GraphQL 呢则是由统一的端点来进行。同时呢,发送的报文呢,也是完整的有固定格式的标准。当然,比如说我在删除一个订单明细的时候,它也是一样,在删除订单明细的时候看, delete order item,这些的话,它都给我们做到了统一的接口和不同的实现。

Speaker 1 00:02:45.040 那么这个具体是如何做的呢?这就是我们今天要聊的事情,为什么 GraphQL 更适合 AI 编程的环境?好的,老规矩,我们回到笔记来进行讲解。在 2015 年的时候, GraphQL 呢,首先是被 Facebook 开源提出来的,那现在大家都知道 Facebook 已经转名叫 Meta 了,那么 GraphQL 呢,在国内使用相对是比较少的。但是在国际上使用的是非常多的,它解决了一个重要的问题,就是RESTful,也就是传统的咱们的 HTTP 接口,它是弱类型的。我们在使用 RESTful 发送报文的时候,必须要去查询各种各样的文案,或者是示例,你才知道,哦,传什么参数,具体有哪些要求。这些是一种隐性的内容,我们还需要配合额外的很多文档进行说明。

Speaker 1 00:03:38.190 但是 GraphQL 不是了。首先, GraphQL 也是基于 HTTP 请求来进行实现的,它本质上和 RESTful 没有任何区别,只不过它对发送的请求的格式有了更明确的要求。比如说最明显的 GraphQL 中,它要求一个强 scanner 的系统。在我们进行业务发送的时候,你所提交的对象也好,还是什么字段也好,并不是一个你想怎么写就怎么写的。而是有明确的说明和要求。比如说当前,如果我们要做某一个用户对象处理的时候,你就可以看到他的用户里边包含了具体的哪些要求。诶,字段名称是什么样的?类型是什么样的?还有他的如果是集合是怎么样的?这个叹号呢,代表的是是否是必填的。

Speaker 1 00:04:27.750 这些描述呢,在我们未来在前端向后端来发送的时候,这种描述呢都会自动的进行校验。而这些东西呢,是以脚本化的方式保存在了我们后端和前端的。这个工程当中。那如果回到咱们自己刚才演示的代码上,那你会发现在我们提供的后端工程中,诶,在业务构建时,这里有一个 Schema GraphQL,打开以后你可以看到当前的在后端工程中所需要进行接收和处理的文档呢,诶,它都描述了到底是有哪些查询,或者是数据的更新,也就是具体的行为、对象以及对象的具体的结构,这些信息全都以独立的文档来进行描述。相当于是一个强类型约束的。

Speaker 1 00:05:20.270 作为后端 GraphQL 它生成了脚本以后,前端呢,自然可以根据来生成前端发送时候的规约。后端脚本用于生成前端的数据的规范。比如咱们现在看到的 fontend 下面有一个 graphql. ts,展开以后你看到它上面的描述呢,就是,我们根据后端的 schema GraphQLS 的脚本文件呢,去生成了前端要进行数据发送的时候,我们包含的。数据类型和具体的情况,在这里都做了一一的对应。而这些呢,在程序运行的时候,会伴随着我们 JavaScript 在发送前,就可以在前端进行前置的校验。

Speaker 1 00:06:05.520 那么你会发现,作为GraphQL,它其实是一种先行的约定,我们在处理的时候,约好,哎,你用什么样的格式?用什么样的字段?我们来进行发送,这便是 GraphQL 最重要的一个点,它呢,进行了一个强约束化。那么第二个,作为GraphQL,如果在后端的话,刚才所提到的,比如说这里的像order。订单,还有 post 文章,这些东西它呢其实自动的就可以和咱们 Java 中的对象和类型呢来进行一个映射。比如咱们映射到的 string 叹号,叹号是非空的意思,它呢就可以对应地映射到 Java 的类型。那如果是 float 这种单浮点型,它会自动的在我们进行反序列化的时候,映射成 Java 的BigDecimal。那么默认的它就会将我们刚才脚本中的对象呢转换为了 Java 的对象,而整体的过程你并不需要做任何额外的转换。

Speaker 1 00:07:06.830 以当前为例,现在我们在 GraphQL 中后台定义到的对象和东西,你会发现在处理的时候,它就会一一的来进行一个对应的映射。如果是一个集合的话,它也会给我们映射成对应的 list order item,一一的进行翻译。这两者呢,是相应对应起来的,而且自动的实现序列化、反序列化。这些工作全都是用 GraphQL 的框架来进行的。至于 GraphQL 的具体的框架应用,不在今天咱们的范围内,我们就先说具体 GraphQL 能够带来什么样的好处吧。

Speaker 1 00:07:42.350 同时, GraphQL 还有一个特别重要的能力,代表自省能力。什么是自省能力呢?就是咱们可以通过对应的查询这个 scanner 的接口呢,或者行为呢,你可以了解到我们某一个具体行为的元信息是什么。哎,你发送的时候,这个接口里边能发送什么东西啊?它不单只是说在代码层面上,你还可以直接通过 API 层面上,像GraphQL,刚才我们的地址呢,发送包含了这样的一个报文,它就会返回了你所需要的。具体的某个 API 本身的结构,根据这个结构,你也可以去做后续的一些额外的工作,可以获取 API 的。

Speaker 1 00:08:25.880 元信息的内容。基于GraphQL,刚才提到的这种脚本的这些东西,咱们在这呢就不展开来说了,其实也是比较简单的啊。我们是先去让大家理解什么是GraphQL。那为什么经过三个月的实践,我们统一的大家私底下都会现在选择 GraphQL 来进行呢?首先第一个, GraphQL 以前在国内用的不多,所以如果手撸编程的时候,它呢是没有优势的。但是现在 AI 的背景下, GraphQL 代码都可以生成了,你会和不会,其实对这个结果。影响不大,只要 AI 会就行。在 GraphQL 中,它特别强化了对于 HTTP 的接口的稳定性的处理。我们通过刚才的 Schema 文件,对输入和输出的结构呢,有一个稳定的处理,有了一个强约束。这对于 AI 来说是一个非常好的说明文件。

Speaker 1 00:09:22.440 在以前,如果我们要进行 RESTful API 处理的时候,其实是一件很痛苦的事情。拿一个特别简单的事。比如在当前的案例中,我们有一个具体的时间的部分DateTime,如果按照以前的 RESTful API,这个 DateTime 到底包含的是什么信息呢?不知道,它可以是一个时间戳,它也可以是一个到毫秒的时间,也可以是一个到秒的时间,这个东西没有过多的描述。但是呢,在 GraphQL 中,因为我们在进行接口设计的时候,就明确了去说明里边的具体的类型和规格,所以呢,它是不会产生歧义的。

Speaker 1 00:10:03.550 AI 在读取到这些内容以后,它可以非常确定的知道我们的数据类型、数据结构是什么样子。同时呢,在业务开发的时候,由于这种元信息呢,可以非常精准的帮我们让 AI 了解到怎么去调用的,这些传参的信息是什么。这些都是以前在标准的 HTTP RESTful 接口中难以做到的。比如以当前为例,我们传入一个订单,那这个订单中的时间是什么格式呢? ISO 的字符串,还是 UNIX 时间戳,还是什么呢?它是没有描述性的。但是在 GraphQL 中,我们用一个scalar,它就可以准确的知道这是一个标准的时间标量。它是有一个标准的格式的。

Speaker 1 00:10:48.650 同时在业务处理的时候,原本的 RESTful API 我们也会发现一些额外的问题,比如这里的 users 123, users 123 post,一个获取用户本身的信息,一个获取文章的信息。处理的时候,这本质上是两个 API 接口,但是呢,从 GraphQL 就可以两者联系在一起,你可以看到在一个 user 中,我们可以去关联到post。在Post,它是个集合嘛,关联到下面的具体的信息,同样的也可以关联到其他的内容。所以呢,通过这样的方式,你一站式的可以解决了原本两个接口来同时获取数据的一个问题。

Speaker 1 00:11:28.420 而且在这个过程中, GraphQL 有一个特别好的应用场景,就是可以对字段进行筛选。比如咱们在有一些场景下,不需要拿到咱们的 Post 具体的文章列表,只需要拿到用户的基本的信息。那么在从前台进行向后传递的时候,你可以指明我们只需要哪些。字段就可以了,而在后台呢,发现,诶?我这里我们没有关联到查询的文章信息,那就不去查数据库嘛。

Speaker 1 00:12:00.050 这些字段完全是可以在 GraphQL 在语法标准层面上就可以实现的。那在我们进行业务处理的时候,可以发现大量的目前的软件工具呢,其实都是可以对 GraphQL 有着良好的支持。比如在前端工具中,通过引入阿波罗, code generator,也就是代码生成器,从后端的 GraphQL 的文件来生成前端的 JavaScript 代码,用于帮助我们简化传参的方式。可以生成前后端一致的数据传递的对象,并不需要我们手动进行开发。同样因为这个东西你生成了,未来你可以随时的进行同步的更新,或者让 AI 呢来读取这些文件,了解到我们本次发送的信息。

Speaker 1 00:12:48.400 针对 GraphQL 的协作流程,其实也是比较简单的。在前端开发的时候,刚才我们不是提到了,通过刚才阿波罗的 code generator,它生成了脚本吗?在不同的环节下,它新增、查询、修改都会统一的向 GraphQL 这个接口呢进行发送,只不过里边的行为不一样。

Speaker 1 00:13:10.730 后端根据发来的请求,首先呢通过 Resolver 对发来的前端数据进行反序列化,反序列化为咱们之前所提前定义的各种后端对象,然后将后端对象传入到 Service 当中来进行后续的处理。那作为这个Resolver,其实你可以把它就看成是我们 MVC 中的控制器的职责。那具体的处理的部分,它也分成了四个阶段。

Speaker 1 00:13:35.530 首先一开始肯定是在后端,我们通过 GraphQL 这个脚本呢生成一系列的对象,这个对象它是。既是脚本,同时呢,也会自动的生成咱们的 order 对象,哎,它是配套出现的,同时呢,可以进行一对一的这种映射。同时呢,在后端的地方,咱们也可以针对它进行具体的实现,比如说针对查询getorder,拿到所有的订单,那你就是该怎么去实现嘛?咱们在后端的 SpringBoot 中,对于 GraphQL 有着很好的支持,以当前为例,其实就对应了咱们说到的 getorders 这个方法,它也是一个自动映射的关系。

Speaker 1 00:14:14.760 这个语法层面上的细节,咱们今天不多去细究。后续在使用的时候,只需要前端往 GraphQL 的地址呢,发送这样的, query get orders 这样的一个脚本,它呢就会自动的去执行里边的具体的 service 代码,最后呢返回的也是格式化好的 data orders 这样的一种标准格式。在按照这样的方式来处理,就可以非常清晰的用一个接口表达不同模块的。不同行为。

Speaker 1 00:14:47.180 那在最后咱们来看一下,作为一个 GraphQL 中,它具体做了什么样的事情吧?首先来看一下一个查询所有订单的方式,那么来查询的时候可以看到它这里边可以去指定我要获取到的对象有哪些,包括items,也就是具体的订单明细中,我们也返回的具体的各个的字段,这些的话都是可以在发送请求的时候,你可以进行一个描述,这些字段被传入到后台以后,后台的话会根据我们传到的字段,最后呢来进行一个。过滤,只去返回前台所需要的字段,无形中呢减少了网络的负荷和后端查询的压力。在下面返回的时候也都是一一的对应上的,这是一个查询的工作。

Speaker 1 00:15:35.250 那么在创建订单的时候也是一样, create order 在后台呢发配到 resolver 处理器,参数是什么?咱们在这里来进行了一个说明,上方呢是具体的要发送的基本的结构和调用具体的方法,从这直接进行表达。那么它在后台呢返回序列化,完成各种处理。

Speaker 1 00:15:56.820 那说到这里,大家应该也明白了吧?这 GraphQL 相对于我们传统的 RESTful API 的话,它有更好的可维护性,是一种强类型约束的。同时在数据处理的时候,因为有完整的约束文档进行表达,更容易被 AI 理解。关联到对应的上下文来实现我们具体的业务开发,让 AI 的工作变得更为清晰。同时因为 GraphQL 是强约束的,所有的操作是以刚才我们看到的文档为基准,所以本身这些文档呢,就是有明确的自描述性,你不会产生一个情况是我们以前RESTful,你写完了以后,同步的去更新对应的document,也就是对应的描述的脚本,在这里不需要,因为它脚本本身就是有说明性的信息。通过一种标准的形式完成了数据的处理,无论是人读还是AI,都是一件。非常好的事情。

Speaker 1 00:16:56.790 最后呢?我也列出来了对应的 GraphQL 和咱们 RESTful 的一些具体的关键需求和区别是什么,咱们可以了解一下。那作为GraphQL,它为什么早期没有被应用呢?其实有一大问题便是 GraphQL 呢,在去年的时候还是在 AI 辅助的前提下才能去做。那今年呢,已经进入到 agent 时代,所有的操作交给了 agent 来进行实现。那 GraphQL 它在国内国外这种人的认知的层面上,以这个边界已经被打破了。所以为什么我们不用更好、更标准化的,更强约束的方式来构建我们的文档和工程呢?好,以上就是今天的内容,希望能对你有一些帮助和启发。


增量追加路径修复验证

来源:文字 | 日期:2026-08-04

第三次:验证增量追加路径已修复,本地与 ima 应对齐。



Prev
哄人
Next
健康