软件工程领域流传着一个根深蒂固的认知:增长必然拖垮性能。

用户多了,数据库查询就重了。请求涨了,服务器集群就得跟着扩。功能堆上去了,bug自然藏不住。会议室里总会有人抛出一句“我们后面再优化”,然后所有人默默接受了一个前提——这款应用从今往后只会越来越慢。

打开网易新闻 查看精彩图片

但如果把目光转向 Google、Netflix、Discord、Amazon、Stripe 和 Cloudflare 这类公司,一个异样的现象便浮出水面。

它们的系统里,大量组件非但没有被规模压垮,反而在用户持续涌入的过程中跑得更快了。

这听上去几乎违背常理。

新增数以百万计的用户,怎么可能让软件变得更快?

背后的逻辑其实相当直白。

这些公司早已不再盯着单次请求的响应速度做文章,转头去对整个系统的运行方式下手。这种视角的切换,彻底改变了软件设计的基底。

小型应用习惯从局部考虑问题。搭建一个简易电商网站时,顾客请求某个商品页面,后端依次查询商品信息、库存、评价、推荐位和卖家资料,最后把结果拼好返回。当数据库里只躺着 1 万件商品,单次查询耗时 20 毫秒,一切看上去毫无破绽。

直到业务量级膨胀到 5000 万件商品、日均数百万独立访客、成千上万个卖家同时要求实时库存更新的那一刻,同样的页面还在一丝不苟地跑满六次重查询。数据库被压到喘不过气,工程师们却还在堆砌服务器——因为问题本身被误读了。

真正成熟的系统,会花大力气停下那些本就不该执行的运算。这是长期观察分布式系统之后得出的最核心的一课:最快的操作,是根本没被执行的那个动作。

“怎么把这条查询的速度再提上去”与“我们到底为什么还要执行这条查询”,两者映射出的是截然不同的工程思维。

但凡不需要实时一致性的数据,就该被缓存挡在前面。初学者倾向于把缓存当成一种优化手段,而经验丰富的工程师心里清楚,缓存本身就是架构。拿新闻网站的一篇文章来说,每个访客都要把昂贵的渲染流程从头走一遍;一旦引入缓存层,成千上万个请求可以连数据库的影子都摸不着就被直接满足。一个极具反直觉的效果随之显现:用户规模越大,缓存的命中率被推得越高,系统在热度攀升的过程中反而变得更加轻快。

这暴露了大型系统的另一个迷人特性——热度本身会制造效率。假定你的应用总共挂载 100 万件商品,但其中仅有 2% 被频繁浏览。这些热门商品会一直待在内存里,留在 Redis 里,留在 CPU 缓存里,随时处于已加载状态,提取成本被压到极低。而那些冷门商品,大可安安静静躺在磁盘上。大型公司有意地利用这一行为,因为它们明白,不是所有数据都有资格享受同等的计算资源。

还有一类重复运算藏得更深。页面上展示的通常是趋势商品、畅销榜、最受欢迎的文章或者人气创作者,初级开发者会在每次请求时都老老实实算一遍,全然不顾这些数据在接下来的数分钟乃至数小时内根本不会发生变化。成熟的系统会直接缓存计算的结果,或者提前把这些内容算好等着直接推送,不再让每次请求触发一连串相同的运算链条。

规模扩大的另一个必然动作,是把同步流程逐步替换为异步处理。用户下单后,系统无需立刻发送确认邮件、扣减库存、更新推荐模型、刷新排行榜、同步第三方物流全部做完再返回成功页面。真正合理的做法是把订单确认快速返回,其余动作排队消解,让用户感知到的延迟与任务的实际计算量脱钩。

一些大型服务还会利用规模优势进行批量聚合。零散写入被汇聚成批次操作,减少对存储层的压力;日志和指标按固定窗口聚合后再落盘,而不是每条都单独触发一次 I/O。被分散到海量用户头上的单位计算成本,反而在规模扩大时下降了。

反向来看,增长也意味着拥有更充足的采样数据去辨别哪些环节最为昂贵,哪些路径从来没人走过。低流量的服务往往连性能瓶颈藏在哪里都不清楚,一旦规模上来,从链路追踪和分布式剖面分析中显现出来的热点便精准地指引着优化方向。每一轮削掉的都是真金白银的计算开销。

这整套思维方式的根基建立在一个朴素的判断之上:真正的系统性能,衡量标尺不是单次请求在真空中的耗时,而是每单位业务价值所消耗的计算资源。将大量现实流量转化为更全面的热点缓存、更精确的批量合并和更果决的运算裁撤,使得系统在业务膨胀的过程中,非但不陷入泥潭,反而获得了越来越多的“捷径”。

当团队还在会议室里为日渐臃肿的服务挠头时,那些把焦点从单次响应挪向系统全局的架构师,已经让代码在增长中跑出了更快的速度。