跑得稳:该花的复杂度要舍得花 📅 发布时间:2026/8/24 14:14:29 👁 浏览次数: 到了「跑得稳」才真正开始谈架构。不是因为你终于可以展示自己知道多少种设计模式了是因为你终于有了足够的信息来做对的选择。一、为什么这时候才该谈架构「能跑」和「跑得准」阶段你也在做技术决策但那些决策的核心是「做减法」——砍功能、砍抽象、砍依赖。到了「跑得稳」你开始做加法了。区别在于前面的减法靠的是直觉和纪律现在的加法靠的是前两个阶段攒下来的真实信息。你不知道用户会不会用的时候上消息队列是在赌。你知道核心链路每天跑几百万条、每条都不能丢的时候上消息队列是在做对的事。同样的决策信息量不同性质就不同。你手里有数据了你知道哪里会出问题、出问题了代价有多大——这时候谈容错、谈可观测、谈灰度不是在给想象中的系统买保险是在给你真实见过的系统补短板。二、该花的三大件容错先承认它会失败容错最难的地方不是技术。是心态。大部分工程师在写代码的时候脑子里的画面是「正常情况」——数据正常进来正常处理正常输出。但生产环境教会你的第一课是没有正常情况。依赖会超时网络会抖动磁盘会满。数据不会按你预想的格式来下游不会在你预期的时间回响应。容错的第一步不是重试、回滚、降级——是先承认它会失败。你承认了每个环节都可能出问题才会去想「出了事怎么办」。重试是「再给一次机会」回滚是「回到出事前的状态」降级是「先保住大部分功能」。不要每个环节三样都做——你承受不起那个复杂度。但每个环节至少有一个兜底方案。重试不了就回滚回滚不了就降级降级不了至少打一条日志告诉别人这里断了。没有完美的系统但要在系统发生故障时能控制住损失。关键不是「怎么恢复」是「别让一个环节的失败变成了所有环节的失败」。大多数系统不是被高并发打垮的是被一个没预料到的失败连锁反应拖垮的。稳定性不止靠技术也靠预案容错告诉你「出了问题怎么恢复」。但还有一个更基础的东西你知不知道自己在出问题的时候该做什么。线上出问题的时候时间是被扭曲的。每一分钟都像一个小时每一条消息都像一声尖叫。人在这种时候会乱——你以为是代码 bug结果只是网络抖了一下你以为只是重启一下结果重启了把缓存全清空了。没有预案的人会瞎操作在压力下乱试一通结果本来一个小故障被手动折腾成大事故。有预案的团队正好相反。有充足的预案在线上出现问题时可以不慌不忙按照操作手册来先确认是什么问题 → 执行回滚/切换 → 确认服务恢复 → 然后再去排查根因。优先保证服务可用性再去做长短期的解决方案。操作手册不是「出了问题去读一遍」是在没出事的时候就写好了放在那里出事了谁来都能照着做。人是会紧张的但手册不会。预案的价值不在于「里面写了什么」在于「出事的时候你不用想」。你照着做就行了——不敢确定是什么问题但确定自己该做什么。可观测不是用来解释过去是用来发现现在大部分人对可观测的理解是出问题了去翻日志查原因。这确实用到了可观测但不是可观测的核心。可观测的核心是在问题还没被用户发现的时候你先知道。日志解释过去——告诉你「刚才发生了什么」。指标发现现在——告诉你「现在正在发生什么」。告警预见未来——告诉你「接下来可能要发生什么」某个队列堆积在涨、某个接口延迟在爬坡还没到报警阈值但方向已经不太对了。告警的价值不在「出了事通知你」在「在还没出事的时候就告诉你你可能要出事」。用户和你同时知道出了问题那是告警没做到位。告警该做的是比用户早一步。可观测的价值不在「出了事能查」在「没出事就知道可能出事」。你早上打开仪表盘看到某个指标在慢慢变差——还没崩还没人报但你在变差了。这时候你出手处理用户不知道你做了什么但用户感受到的是「这东西一直很稳」。灰度不是胆小是给自己留退路敢直接全量切换说明你对系统还不够了解。灰度发布的核心逻辑不复杂一个变更只影响一小部分用户出问题了影响面在小部分里全量了影响面在全部里。区别不在技术自信在代价大小。灰度不是不相信自己是不想把所有用户的信任都押在自己的「我相信没问题」上。灰度的背后是两条更根本的原则。第一条留好退路可以回滚/撤回最小化损失。灰度的价值不止在于「慢慢放量」更在于「出了问题能立刻撤回」。没有哪个变更能保证零 bug——有退路你才不会在问题发生时被锁死。撤回不是在承认你错了是在说你知道怎么保护自己。第二条出现问题优先解决而非追责或调查根因。灰度的流程是发现异常 → 立刻回滚 → 恢复服务 → 然后再查原因。不是先查根因再回滚——你查根因的这段时间用户还在受影响服务还在坏着。先止损再复盘。把影响控制在最小范围把时间花在解决问题上而不是花在「谁写的这个 bug」上。三、不要为「万一」做架构复杂度不是免费的。每一份复杂度都有维护成本——你加了重试逻辑重试本身也可能出错重试的次数、间隔、幂等逻辑都要维护。你加了监控监控本身要占资源指标采集、告警配置、阈值调优每一个都在吃你的时间。你加了灰度灰度就要维护流量路由、用户分群、回滚方案——这些都是复杂度不是一次性的代码是持续性的责任。所以「该花的」和「不该花的」之间有一条很清晰的线看成本。不是看「这个方案能不能做到」是看「做这件事的成本能不能被业务风险抵回来」。一个日活几百的内部系统上微服务、分库分表、多活容灾——出一次故障损失几十块钱但那套基础设施每个月的维护成本是几千块钱。学会做减法。日志要打但不能打崩系统——日志量上来把磁盘写满了你加了一个「保障」结果自己成了故障源。预发环境要有但要在成本允许的范围内——花几十万搭一套和线上 1:1 的预发为了提前发现一个几周才出一次的问题不值。把复杂度和思考放在产生最大价值的地方。不是所有环节都要容错是最核心的链路要容错。不是所有指标都要监控是业务最敏感的那几个要监控。不是所有变更都要灰度是影响核心链路的变更要灰度。四、案例不该花的复杂度长什么样第2篇里讲过一个 Airflow 的案例——定时任务只有两个但搭了一套 Airflow结果每个月花时间维护 Scheduler、Worker、元数据库。那是「能跑」阶段的过度设计。「跑得稳」阶段也有类似的坑但更隐蔽——不是「不该用」是「用了但没花对地方」。曾经做过一个数据入湖链路单机跑没问题数据量上来后怕挂。加了 checkpoint——挂了能从断点续跑不用从头再来。这个复杂度花对了——多写了几十行代码换来的是凌晨三点不用爬起来手动重跑。但接着有人建议「再加一套自动故障转移把单机变双活」。这个就花错了——链路本身不要求高可用挂了停几分钟再起来没关系。双活带来的同步开销、脑裂处理、状态一致性维护成本远超收益。最后没做把时间花在了别的地方。判断一个复杂度该不该花的唯一标准你知不知道这个复杂度在解决什么问题。你知道核心链路每天跑多少条、每一条丢了代价多大——你知道你就能判断。你不知道你就是在一个场景还没看清楚的时候给系统加了一道锁。不是锁扣上用不上——是锁本身就是成本你在为「可能」买单而不是「需要」买单。五、稳定性也在消耗信任「跑得准」那篇讲过准确性出一次错信任就崩了。但稳定性也在消耗信任只是消耗得更慢、更难察觉。曾经做过一个项目用到了 GCP 上的一个离线计算服务 Dataproc。选型的时候看中了它启停比 AWS EMR 快Dataproc 不到一分钟就能起来EMR 要几分钟。而且启停时间本身也是计费的——有些任务只跑几分钟光启动就花了两倍的时间成本。但上线后Dataproc 频繁因为机器资源紧张或系统升级导致服务不可用——不是你代码的问题是它底层基础设施的问题。每一次不可用都直接影响了数据的交付时效客户支持团队承受了巨大的压力。不是一两次是反复、持续性地出问题。用户不关心是哪个环节的问题。他们不关心是你代码的问题还是云服务的问题——他们只看到「数据没按时到」。最后公司因为续费单的损失下定决心把全线迁移到内部云。Dataproc 启停快是技术上的优势但在线上频繁不可用面前那个优势被消耗得一干二净。用户不关心你选了什么底层技术只关心数据什么时候到。你选了更快的服务但交付不了确定性的输出——那个「快」就没意义了。六、退出信号什么时候「跑得稳」过了第1篇给过一个信号你能安心睡觉了。这不是玩笑是一个真实可感的指标。你不躺在床上想「系统会不会炸」——不是因为你加了最牛的监控是因为你知道即使炸了也有兜底即使不炸也在被看着。你知道核心链路上有重试、有降级、有告警。你知道一个组件挂了不会拖垮全部。你知道数据丢了有 checkpointer 能续回来。这些都是你前两个阶段攒下来的认知。你知道了系统的核心在哪、瓶颈在哪、什么能丢什么不能丢——你花钱的时候知道自己在买什么。你不是在买一个「可能更好」是在买一个「已知需要」。收尾「能跑」阶段你在做减法「跑得准」阶段你在换站位「跑得稳」阶段你在做加法。生产环境要的是确定性的输出不是偶尔惊喜。跑得准了就把它稳下来。