凌晨两点四十七分,监控大屏上那个代表核心交易链路的绿色指标突然拉成一条刺眼的红线。紧接着是告警电话、故障群刷屏、用户反馈截图从四面八方涌来。六个小时后服务才逐步恢复,而这已经是一周内第四次被拉出来“公开处刑”的严重事故。当“AI写代码”和“裁员1.6万人”这两个词同时出现在一份紧急复盘报告里,所有人的第一反应都是:这锅到底该谁背?
我直接说结论:这种级别的连环故障,几乎不可能只有一个根因。把锅甩给裁员,或者甩给AI写代码,都是一种偷懒。真正的复盘应该回答的是——在组织剧烈变动和技术栈快速迭代的双重压力下,我们的系统韧性到底被哪根隐性链条击穿了?这篇文章不讨论“该不该裁员”,也不替任何公司洗白,只从工程实操的视角,把这条链条一根一根拆开看。
1. 先别急着画因果线:裁员和宕机为什么总被绑在一起
1.1 “两条新闻并排”的传播心理和时间线陷阱
人脑天然喜欢归因。当一个6000万级用户的平台公布裁员消息后,紧接着爆出一次6小时宕机,媒体和舆论几乎不需要思考就能画出这么一条因果链:裁员——人手不足——系统维护不到位——出事。这个链条看着顺理成章,但它忽略了一个最基本的统计学常识:相关不等于因果。
我参与过不少故障复盘,一个被反复验证的真相是,大型互联网系统的故障频率本身就是一个波动曲线。即便什么都不改变,每个月出现一两次中等规模事故都是正常的。要判断裁员和服务稳定性之间是否存在真实关联,你得先建立一条基准线——过去一年里,这个平台平均每周发生几次P0/P1事故?故障平均恢复时长是多少?这些指标在近半年是上升还是下降?没有这些数据支撑,单凭“裁员之后崩了”这六个字,本质上就是在做一个没有对照组的实验。
时间线还有一个更大的陷阱:裁员消息公开的那一天,往往不是组织变动真正的起点。真正的动荡从冻结招聘、削减成本、内部转岗、核心团队出走这些信号出现时就开始了,而这些内部信号外界根本看不见。所以外界看到的“裁完就崩”,在系统内部可能已经酝酿了几个月。同理,AI写代码也不是某一天突然出现的,它可能已经默默在生产环境里跑了很久,只是这次事故让大家把目光聚焦到它身上。
1.2 裁员真正侵蚀系统稳定性的四条链路
我在给一些创业公司做技术顾问时,经历过几次人员剧烈变动的阶段。裁员对系统稳定性的伤害,不是“少了几个人干活”这么简单,它实际上通过四条链路逐步渗透:
知识断崖是最直接的一条。一个系统运行三年之后,它的行为逻辑很大部分不在代码里,而在老员工的脑子里。那个“凌晨四点非高峰期不能跑批任务”的经验,那个“这个配置项改了会导致下游某个服务超时”的教训,都没有写进文档。人一走,知识就跟着蒸发了。哪怕走之前做了一个月的交接,交接文档能覆盖的信息量通常不到真实经验的百分之二十。
响应链路断裂是第二条。所有在线系统都需要一套成熟的oncall机制——谁负责盯告警,谁负责第一响应,谁负责根因定位,谁负责恢复操作。人少之后,这些角色没办法一一对应,一个SRE可能要同时盯七八个完全不同技术栈的服务。人的注意力带宽是有限的,告警风暴一来,很容易在高优先级和低优先级告警之间做出错误判断。尤其是深夜,一个人被三条链路的告警同时轰炸,出错概率指数级上升。
变更节奏失衡是第三条。为了保证业务连续性,正常团队会刻意控制生产环境的变更节奏——周一到周四部署,周五冻结;大促前两周冻结所有高风险变更。裁员过程中,业务目标不会消失,反而会因为人手减少而把变更批量压缩。一次发版塞进原来三周的变更量,出问题的概率不是线性增长,而是指数增长。
组织信任瓦解是第四条,也是最隐蔽的一条。裁员消息一出,留下的人心里想的是“下一个会不会是我”。这种心态下,没人愿意主动去接高风险项目,没人愿意当那个“生产环境出了问题要被追责”的owner。系统维护从“主动发现并修复”变成“不坏就不碰”,而基础设施这类东西,恰恰最怕不被碰。
把这四条链路叠加在一起,你会发现一个残酷的现实:裁员后系统故障率上升,未必是人不够用,而是组织对系统复杂性的“认知承载能力”大幅缩水了。那些看起来平平无奇的日常巡检、容量预估、故障演练,在大规模人员变动期,才是真正决定系统命运的生死线。
2. AI写代码的锅,到底该不该背
2.1 AI生成代码的真实工作方式与失效模式
这几个月“AI写代码”几乎成了一个万能背锅侠。任何线上事故,只要代码审查记录里出现一行“由AI生成”,就会在复盘会上被单独拿出来批斗。但作为一个从Copilot时代就开始用AI辅助编程,现在深度用Qwen Code这类开源模型做日常开发的工程师,我必须说一句公道话:AI不会主动引入事故,引入事故的是那个不对AI输出做校验的人。
理解这个问题,你得先知道AI写代码的工作机制。以Qwen Code为例,它的核心能力是“带约束的文本生成”——模型根据你输入的注释、函数名、调用上下文、导入的第三方库等信号,预测最可能的下一个token序列。它不是一个逻辑推导引擎,而是一个概率模型。这带来三个非常关键的工程特性:
第一,它对“正确性”的理解是统计层面的“像”,不是逻辑层面的“是”。你让它写一个二分查找,它极大概率能写出标准解法,因为训练数据里见过成千上万遍。但是让它处理一个带有业务特殊规则的边界条件——比如“当订单金额等于0时不能走优惠券校验,但要记录风控日志”——它就很容易凭借“经验”猜一个并不存在的规则。
第二,它会把训练数据里的历史错误当成“正确”继承下来。如果你的代码库里大量出现某种反模式,比如在循环里做数据库查询,模型下次生成代码时也会倾向于复现这种写法。
第三,它对当前代码库的真实运行环境并不了解。它看不到你的线上流量分布、缓存命中率、数据库慢查询报警阈值。它生成一段看似合理的代码,却可能因为对一个接口超时时间设置不当,在高并发场景下把整个依赖链拖垮。
失效模式就更常见了。我归纳了四类:幻觉API——生成一个调用了不存在的方法或参数名,靠IDE检查能拦住一部分;边界条件丢失——只处理了happy path,抛异常路径完全没写;上下文截断——处理长文件时,前半段的变量定义和后半段的业务逻辑割裂;依赖膨胀——为了一个小功能自动引入一个重量级库,制造新的安全风险面。
2.2 从设计稿到嵌入式:AI代码在不同场景的风险等级
“figma 将设计图转给ai写前端代码”是最近特别火的一种用法。我实际验证过,把一张设计图丢给AI,让它生成React组件,体验确实非常惊艳——布局、颜色、间距几乎一比一还原。但这类生成代码通常停留在“静态展示层”,它不包含真实业务的状态管理、接口调用和异常处理。如果你拿它直接接到生产环境,第一个请求进来可能没事,但当用户在这个组件里连续操作五次以上,就开始出现内存泄漏、状态不同步这些只在交互场景下才会暴露的问题。
“嵌入式全靠ai写代码”这个热词就更有意思了。嵌入式开发对代码的要求和Web开发完全是两个物种:它需要精确控制时序,需要处理中断优先级,需要理解寄存器级的硬件行为。这些约束在训练数据里并不充分,而且硬件型号一变,模型很容易给出看似合理实则错误的寄存器配置。哪怕错误只发生在某个冷门的低功耗模式切换上,产品都要在客户现场折腾很久才能定位。我把这类风险等级划为:生成静态页面属于低风险,生成CRUD接口属于中风险,生成并发控制、硬件驱动、支付核心逻辑属于高风险——高风险意味着AI只能当草稿生成器,最终的安全边界必须由人类工程师严格兜底。
2.3 “代码是AI写的”为什么不能当免责声明
有一种特别危险的论调:“我用了AI写代码,所以事故是AI的锅。”我甚至在一些技术管理者的复盘报告里看到这种甩锅话术。这种认知必须被纠正:AI写代码这件事,本质上和“程序员从GitHub上复制了一段代码”没有任何区别。你从Stack Overflow上抄一段代码回来,出了事你会说“是Stack Overflow的锅”吗?不会,因为谁都清楚,把代码放进生产环境的那一刻,责任主体是那个按了部署键的工程师和批准了变更的reviewer。
AI代码更隐蔽的风险在于它的“虚假可信感”。人类写代码的时候,遇到模糊需求会下意识停下来问。AI不会停,它会用行文流畅但你完全没验证过的逻辑,填补所有需求空白。如果你带着“AI已经写完了,肯定没问题”的心态去review,你就等于把思考外包给了一个概率模型。正确的姿态是什么?把AI当做一个能力极强但非常不靠谱的实习工程师。他交上来的每一段代码,都必须经过完整的代码评审、单测验证、灰度观察,才能视为“候选代码”。做到这一点,AI代码就不会成为事故元凶;做不到这一点,事故只是迟早的问题。
3. 一份克制的事故复盘应该长什么样
3.1 6小时宕机的时间线应该怎么重建
回到标题里说的“网站再崩6小时”。很多人对6小时没有概念——在大型互联网公司,一个P0事故的目标恢复时间通常是以分钟或小时计,超过六小时意味着什么?意味着告警响应中间可能出现了断层,根因定位可能发生了方向性错误,或者是恢复操作本身就触发了二次故障。
一个及格的故障时间线,至少要把六个阶段说清楚:首次发现——是哪条监控曲线的哪个指标率先触发阈值,页面没法访问的User Impact是怎样的;告警升级——第一响应人是谁,到达时间,第一次评估的结论是什么;初步缓解——有没有做过服务重启、流量切走、降级开关这些应急操作,哪个操作暂时缓解了症状,哪个操作反而加重了;根因定位——确认的第一个可疑对象是什么,后来的真因是什么,二者之间是怎么切换的;最终恢复——执行了哪个操作之后核心指标回到正常水位;后续确认——流量恢复后,积压的数据是否对下游造成二次冲击,用户侧看到的异常订单、重复扣款如何补偿。
我在排查一个类似事故时发现,很多团队记录时间线喜欢“报喜不报忧”,比如把“重启失败”和“多次重试”这些操作合并成一个“尝试重启”。这是复盘最要不得的地方。真正有意义的不是那个最终成功的恢复动作,而是那条弯弯绕绕的试错路径。正因为走了弯路,复盘才能回答“下次怎么才能不走弯路”。
3.2 五问法在事故复盘中的正确与错误用法
很多人一提复盘就背“5 Whys”口诀,但我在实际工程中见过太多错误的五问法:问出来的答案总是同一句话的换形式——“因为监控不够完善,所以没发现;因为监控不够完善,所以处理慢;因为监控不够完善,所以……”问到最后等于没问。
正确的五问法应该沿着“技术事实—组织行为—流程缺陷—文化诱因”这条路径层层下钻,而且每一问都必须有一个可验证的“证据锚点”。我举个例子:假设根因是“数据库连接池被占满导致服务不可用”。第一问,连接池为什么被占满?答:一个慢查询把连接全部卡住。第二问,这个慢查询为什么能上线?答:它改动了一个核心表结构但没做性能回归测试。第三问,为什么没做性能回归测试?答:因为发布计划被压缩,测试窗口从三天变成半天。第四问,为什么发布计划能被压缩?答:因为业务方认为这个改动是低风险索引优化,技术负责人没有给出充分的反对意见。第五问,为什么技术负责人没坚持?答:他刚接手这个组件不到两周,上一个负责人已经离开了,他对自己评估的信心不足。
你看,这样问下来,问题从技术层走到了组织层,根因不再是“某个人写了一个慢SQL”,而是“核心系统的知识交接不完整加上变更评审机制缺少技术否决权”——这两个原因,才是真正能指导制度改进的东西。
3.3 官方复盘的“结论先行”为什么危险
官方说的“跟裁员无关,也不是AI写代码的锅”,这句话从公关角度看无可厚非。但从事故复盘的方法论来看,任何“结论先行”的复盘都必须被审慎对待。事故复盘的第一原则是“让证据说话,而不是让立场说话”。如果你先设定好一个“此事和人员调整无关”的前提,再去翻监控数据,你的注意力会不由自主地跳过那些指向“和人员有关”的异常信号——比如两个核心服务的owner变更记录、同一时间段减少50%的巡检执行次数。
一个更可靠的做法是“反向验证”。假设结论成立,反推这个结论能不能解释事故链上的每一个环节。比如“不是AI的锅”,那你就得验证:事故代码是AI生成的还是人写的?如果包含AI代码,那AI代码有没有经过同等严格的评审流程?“不是裁员的锅”,那你就得回答:去年同期同样规模的事故,从告警触发到恢复分别花了多少时间?人员变动后这个指标有没有出现可观测的恶化?如果连这些问题都答不上来,那这个“无关”的结论就下得太早了。
我在自己的项目复盘里有个习惯:复盘第一稿永远不出“结论”,只出“时间线、证据链、疑问点”三个清单。结论是所有人一起讨论出来的,而且允许有不同声音。这比任何号称权威的“官方复盘”都有价值。
4. 把系统的韧性建在组织动荡之上
4.1 人员变动过渡期的稳定性优先级排序
如果你们公司恰好正在经历类似的人员变动,又或者是几十个人的技术团队换了一波核心成员,我的建议是:不要试图“维持正常节奏”,因为那已经不现实了。你需要做的是重新建立一个“过渡期优先级”,按下面的顺序排:
第一优先级:保护核心交易链路。把支付、登录、数据存储这三条线上的人力——不管几个人——优先保障住,代码冻结、运维值守、告警响应全部向它们倾斜。那些边缘业务、内部工具、中台改造项目全部暂停或者降级为“有人看但没人改”的状态。
第二优先级:自动化接管重复性运维。把原来靠人盯的巡检动作尽可能脚本化。告警通知要进入IM,能自动恢复的指标直接加自动化自愈脚本,备份验证和容量评估全部安排上定时任务。
第三优先级:知识资产的紧急固化。把老员工脑子里那份“系统行为说明”用访谈的方式抠出来,落到wiki上。前期不用追求结构化,哪怕就是一堆“xx服务在xx情况下会慢,不要重启只能扩容”这种碎碎念,也值回票价。
第四优先级:建立过渡期变更委员会。哪怕只有一个人也行,但这个人必须对生产环境的变更拥有一票否决权。所有能等一周的变更一律推迟,不能等的变更必须附带详细的影响评估和回滚方案。高峰期和节假日前三天冻结一切非紧急变更,这条规则在任何组织状态下都不要破例。
这套排序的精髓是:承认系统可能有局部降级,但保证最核心的业务不会整体失守。
4.2 面向AI生成代码的四道质量关卡
如果团队里已经有同事用AI写代码,我不建议一刀切禁止。禁止一个被证明能提升效率的工具,本身就是一种效率损失。但你要为它建立一套“AI代码专属质量关卡”,我实战下来有四个:
关卡一:强制“人味”代码评审。AI生成的代码必须走完整的Pull Request流程,评审人不看“代码能不能跑”,而是看“这段代码违反了哪些团队规范、遗漏了哪些边界处理”。评审记录里要明确标注“本段由AI生成,人工评审结论:通过/不通过”。这个标注不是为了追责,而是为了让评审人意识到自己的责任变大了。
关卡二:单测覆盖兜底。AI生成的新代码,函数级别的单元测试必须补齐,核心业务逻辑的分支覆盖率不能低于80%。AI生成代码时通常不会自己补测试,但你完全可以让AI把测试也写了——这是AI比较擅长的部分。让AI生成的代码和AI生成的测试互相牵制,虽然不能保证逻辑绝对正确,但至少能把低级错误大部分过滤掉。
关卡三:灰度发布强制。凡是包含AI生成代码的变更,必须走灰度发布流程。先放到一台机器上跑观察期,再看能不能扩大到一个可用区,最后才全量。这个流程在AI辅助编程普及之前就应该存在,但现在它又多了一个必要性:AI生成代码的“隐性依赖”常常是Human review发现不了的,只能靠真实流量来暴露。
关卡四:依赖锁定与出处审计。AI生成代码时喜欢顺手引入各种第三方库。你需要建立一份“允许使用依赖清单”,凡是清单之外的库,AI生成的代码哪怕能用也得改掉。这能防止AI根据训练数据里的“习惯”引入一个你完全没评估过安全性的库。
4.3 从“追责”到“追因”:事故后的组织学习机制
事故复盘最糟糕的结局,是它变成了“找一个最该负责的人,让他签一个改进计划”。这会让所有人学会一件事:隐瞒。只要把问题藏到下一次爆发前,这轮就过去了。这种“追责文化”在组织动荡期尤其致命——因为没人想当那个“在裁员后留下把柄”的人,于是所有问题都被压在水面之下。
有建设性的机制是**“无指责复盘”**。每一次事故复盘会上,关于人的描述只准出现“做了什么、在哪个时间点、基于什么信息做了决策”,不许出现“某某疏忽、某某不负责任”这类道德评价。大家共同回答三个问题:这个人的决策在当时掌握的信息下是否合理?如果要做出不同决策,他需要哪些他当时没有的信息或支持?这些信息或支持为什么没有被提供?
你会发现,当问题被这样问的时候,答案往往指向“系统设计缺陷”而不是“个人能力缺陷”。比如那个没能拦住问题发布的reviewer,他不是不懂技术,而是他当时有两个会议同时在进行,而且评审系统没有提示他这次变更包含了未经灰度验证的新代码。这些信息,只有从系统层面去补齐才有效。
结语:别让复盘变成表演
回到这次“6小时宕机”的事件本身。我无意断定这家公司的复盘是否诚实,毕竟我没有内部数据。但我想给所有做技术管理和一线研发的同行们一条建议:当外界一窝蜂用“裁员”或“AI写代码”来解释一场事故时,恰恰说明真正的问题还没被找到。真实的事故往往是几十个微小因素交织在一起的结果,和单一事件形成强关联的叙事,多数时候是为了让人“安心”而不是为了让人“理解”。
我自己的习惯是,遇到这种级别的复盘,会带一个小团队把公开信息里的时间线、变更列表、官方结论全部列出来,自己走一遍“如果我是当值的SRE,我会在哪里、以什么方式发现异常、第一次处理动作是什么”。这套推演不一定能还原真相,但每一次都能让我的应急意识提升一个量级。技术世界没有银弹,组织和代码的变化总会带来新的脆弱面,唯一的解法是保持敬畏、持续演练、诚实复盘。