02 | AI 时代,不破不立:程序员的旧能力,需要重新编译一次
AI 时代,不破不立:程序员的旧能力,需要重新编译一次 > 随着 AI 时代的来临,所有涉及到网络的技术类工种,都越来越焦虑。再加上各种自媒体的夸张和渲染,焦虑让人无法呼吸。让人感觉非常焦虑和浮躁。但是焦虑和浮躁的本质原因是什么呢? 怕被取代,这是一个表面现象。并不是问题的本质原因。我的结论是: 怕是对未知事情的不了解。 > 浮躁是想跳过过程直接拿到结果。 - 焦虑是因为对结果的不确定性。 >...
AI 时代,不破不立:程序员的旧能力,需要重新编译一次 > 随着 AI 时代的来临,所有涉及到网络的技术类工种,都越来越焦虑。再加上各种自媒体的夸张和渲染,焦虑让人无法呼吸。让人感觉非常焦虑和浮躁。但是焦虑和浮躁的本质原因是什么呢? 怕被取代,这是一个表面现象。并不是问题的本质原因。我的结论是: 怕是对未知事情的不了解。 > 浮躁是想跳过过程直接拿到结果。 - 焦虑是因为对结果的不确定性。 >...
交付可迁移的性能治理包 性能改造结束后,团队经常留下一份汇报:接口快了多少、数据库压力降了多少、峰值扛到了多少。过几个月再问“对应哪次构建、哪份数据、哪些开关,怎样回退”,答案开始散落在聊天记录、监控截图和某个人的电脑里。 这样的结果很难审计,也不能安全迁移。数字脱离实验现场后只剩结论,配置脱离适用边界后则可能变成下一次事故的输入。 小编更愿意把性能治理的交付物看成一组相互引用的工程资产:代码和配...
做一次可归因的全量回归 从 0201 到 05-02,订单系统先后减少请求、缩小 SQL 工作量、批量访问、调整并发预算、拆分异步链路,又补上超时、隔离和入口容量保护。现在把所有开关打开,与最初版本各跑一轮,最终版确实更快,能否据此给每项改造记功? 不能。缓存可能遮住 SQL 改造的收益,批处理可能改变连接持有时间,异步化也可能只是把耗时移出响应窗口。实验若总按“旧版在前、新版在后”的顺序执行,缓...
用限流与背压守住容量边界 系统在过载时最危险的表现,往往不是立即报错,而是继续接收请求。 吞吐量已经不再增长,队列却越来越长;调用方暂时只看到响应变慢,随后线程、连接和内存一起被占满。等到错误率明显上升,系统早已离开可恢复的运行区间。0501 用超时和隔离封住了单个慢下游,本篇继续处理入口流量超过整条业务链可持续容量的问题。 小编现阶段的理解是:容量治理要尽早拒绝确定做不完的工作,并把有限资源留给...
用超时与隔离封住慢下游 重试已经受控,不代表订单服务就安全了。 一个下游请求超过用户能接受的等待时间后,外层接口可能已经返回超时,但执行请求的线程、连接和下游任务仍然活着。如果这些“已经没人等、却还在干活”的调用不断积累,慢下游最终会拖满订单服务的公共线程池和连接池。那时,原本不依赖它的请求也会一起变慢。 这里要同时解决两个问题:超时决定一次等待何时止损,隔离决定一次故障最多占用多少资源。 只有超...
已经保证订单与事件一起落盘,也接受生产确认和消费确认窗口中的重复。链路不会静默忘掉工作了,新的问题随之出现:下游持续超时、消息一直重投,待处理量越积越多。 最省事的配置通常是“失败就重试”。它对短暂抖动有效,对权限错误、消息结构不兼容和业务状态冲突却没有帮助。相反,同一批失败工作会持续抢线程、连接和下游配额,把原本健康的消息也拖慢。 小编更愿意把重试看成一笔有限预算。每次失败先分类,再决定等待、终...
已经确定:订单提交接口返回时,核心订单事实必须可以查询,通知等后续动作允许延迟完成。接下来要补上那段最危险的空白——数据库已经提交,后续动作却还没有被可靠接走。 直接在事务方法里调用消息客户端,看起来只多了一行代码,实际上会留下两个无法同时消除的窗口:先发消息,数据库可能回滚;先提交数据库,进程可能在发消息前退出。把发送代码换成 ,只会再增加一个内存队列,并没有让两个资源共享一次提交。 小编对这类...
已经让同步工作在可解释的线程和连接预算内运行。再往后压缩延迟,常见做法是给通知方法加上 ,让接口早点返回。 代码少了几行等待,业务承诺却可能在不知不觉中改变。原来接口成功意味着订单、库存和通知都已完成;改造后,它可能只意味着某个任务被放进当前进程的线程池。进程在下一秒退出,调用方仍拿到了“成功”。 在小编看来,异步边界不是线程边界,而是承诺边界。先写清接口返回时必须成立的事实、尚未完成的状态和后续...
已经减少逐条访问,并测出了批次执行时间和连接占用。接下来很容易走进另一个误区:既然单批可以执行,那就多开一些线程并行跑。 线程数加上去后,吞吐可能短暂提高,也可能只是把等待从入口搬到任务队列,再搬到数据库连接池。工作线程拿不到连接时并没有做业务工作,却仍占着线程;队列继续接收任务时,调用方看到的不是明确过载,而是越来越长的尾延迟。 小编不会先问“线程池配多少”。先要回答的是:数据库和其他下游在当前...
已经把一条订单查询内部的扫描、排序、返回字段和对象装配收窄。接口仍可能慢在另一处:列表先查一批订单,随后在循环里为每个订单查询明细;批量任务也可能逐条执行更新,每次都承担一次数据库往返。 举个简化场景。一页订单已经返回若干 ,代码却反复调用 。单条 SQL 的执行计划都很正常,入口请求仍会产生“列表一次 + 每个订单一次”的访问。问题不在某条 SQL 特别慢,而在固定开销被重复支付。 小编对批处理...
前一章已经尽量让重复请求、热点读取和并发回源消失。剩下的订单查询仍然要访问数据库,这时再用缓存命中率解释延迟就不够了:一条查询到底读取了多少候选行、排序了多少结果、返回了多少字节,应用又装配了多少无用字段? 举个简化场景。订单列表页面只展示订单号、状态、金额和创建时间,旧接口却执行 ,允许不受约束的历史范围,使用深分页,再把完整实体转换成列表 DTO。即使最后只返回几十行,数据库和 Java 代码...
举个简化场景:一个热点订单的缓存刚好失效,二十个请求几乎同时到达。二十次 Redis 查询都返回 miss,随后二十个线程一起查数据库。缓存平时的命中率可能很好,数据库却仍会在这个短窗口承受尖峰。 已经处理了缓存对象、数据偏差和失效路径。本篇只补它留下的一个缺口:同一缓存键正在回源时,后来的请求复用这个进行中的结果。小编把这类机制理解为“合并同一时刻的重复工作”。它不延长 TTL,也不改变业务允...
订单详情是热点接口,就一定应该加缓存吗?如果用户正在确认刚完成的状态变化,返回旧数据可能比慢一点更糟;如果一次详情查询本来只查主键、数据库也没有压力,缓存增加的序列化、内存和失效路径未必划算。 已经把业务意图、入口请求和数据库成本连起来。只有清单中那些读取频繁、数据可复用、下游成本明确,并且业务允许有限时效偏差的候选,才值得进入缓存设计。 小编对缓存的理解比较克制:它是用一段明确的数据偏差窗口和...
订单状态接口 QPS 很高,能不能先把轮询频率降下来?同一个订单在短时间内被查询多次,看起来像重复请求,但其中可能包含用户刷新、客服查询、支付回调后的状态确认,也可能只是前端组件重复挂载。只凭 URL 和时间间隔,很容易把合理并发和无效放大混在一起。 上一章已经固定实验条件、构造负载并建立了瓶颈证据链。进入请求减量后,小编更愿意先做一件不那么“像优化”的工作:让每个入口请求能够回答是谁发起、想完成...
压测期间应用 CPU 升到高位,同时出现几条慢 SQL,线程池队列也开始增长。应该先改 SQL、加线程,还是扩容?只看这组现象,三个答案都缺证据。 CPU 高可能是系统正在有效工作,也可能是无效重试消耗;慢 SQL 可能拖住请求,也可能只占很小的流量;线程排队既可能是原因,也可能是下游变慢后的结果。监控面板把它们放在同一时间轴上,不等于已经给出了因果关系。 小编现阶段更看重一条能被推翻的指标链:负...
一个订单详情接口跑出很高的 TPS,不代表订单系统能承受同样规模的业务流量。真实访问里还混着列表查询、状态轮询和订单提交;有些请求集中打到少量热点订单,有些会触发数据库写入和下游调用。把这些差异抹平,只保留单接口恒定并发,最终测到的往往是一个很难用于改造决策的数字。 小编现阶段的判断是:基准负载要描述业务请求怎样到达系统,而不只是描述压测端开了多少线程。请求组合、到达节奏、数据命中分布和下游行为共...
一轮压测跑出 ,优化后变成 ,能否据此宣布收益?还不能。第二轮也许换了机器,Redis 已经热起来,数据库数据少了一半,或者统计工具把超时请求排除在延迟分位数之外。数字确实变好了,但变化未必来自代码。 小编现阶段的判断是:性能改造的第一项产物应当是一份能重建测试现场的基线协议。它记录实验输入、执行过程和测量方式。如果协议不能固定这些比较条件,实验结果就只能算一次观察,不能用来决定某项改造是否保留。...
aweiai-gf-169.webl 一行一行看代码的时代结束了,程序员要开始对结果负责 前言 AI 时代,程序员需要调整的可能不只是开发工具,还有我们看待代码、责任和个人价值的方式。 当然,这并不是什么行业共识,也不是一个已经被证明的标准答案。只是小编最近使用 AI 开发时,越来越明显地感受到:过去那套逐行编写、逐行阅读、逐行确认的工作方式,已经有些跟不上 AI 生成代码的速度了。 过去,小编也...
一套工作流连续推进到第十二篇文章,很容易让人产生错觉:既然流程能跑,模板就已经成熟,可以原样复制到所有项目。 磁盘上的材料给出了更克制的结论。前十一篇都经历了独立审阅,四篇需要修订后复审;项目规则、角色、交接、验证和恢复演练都有真实文件支撑。但这次贯穿对象仍是 JVS 内容生产流程,并没有在另一个真实业务仓库完成一次功能修改或重构。配图和发布也没有进入本轮授权范围。 小编现阶段的判断是:可复用的不...
“接着上次继续。” 任务刚暂停几分钟时,这句话似乎没问题。时间一长,或者换了线程、角色,当前上下文里未必还保留那次执行的完整细节。更危险的是,磁盘已经发生变化,模型却沿用旧计划:重复创建文件、再次发送外部请求,或者把用户后来改过的内容覆盖掉。 小编现阶段的判断是:恢复不是找回一段完美记忆,而是从可信检查点和磁盘事实重新回答三个问题:现在到底是什么状态,旧授权还剩多少,下一步怎样做才不会重复破坏。 ...