复杂系统实战

我在 Google 的经验与教训

Teiva Harsanyi 2025年5月7日

大家好!今天,我们来讨论一个引人入胜的话题:复杂系统。

引言

在我的职业生涯中,我曾在许多复杂的环境中工作。例如,我曾在 Uber 的竞争对手公司从事优化网约车中司机与乘客匹配的工作。与其他情况一样,这个背景在技术上具有挑战性。然而,就复杂性而言,没有什么能与我目前在 Google 的经验相提并论,并且在那里两年的工作经历让我对复杂性的理解更加深刻。

在这篇文章中,我们将拆解复杂性的概念。接下来,我们将退一步来理解是什么让某些环境比其他环境更复杂,然后探讨有效驾驭复杂系统的模式。

复杂 (Complicated) vs. 复杂 (Complex)

理解复杂 (Complicated) 和复杂 (Complex) 问题之间的区别至关重要,因为每种问题都需要从根本上不同的方法:

回到软件工程,在 Uber 的竞争对手公司,其中一个挑战是为乘客高效地找到最近的司机。这远非易事,但它本身并不 复杂 (Complex) 。实际上,存在许多解决方案,例如应用地理哈希(例子),而实施这些解决方案之一是正确的方法。

在 Google,我是一名站点可靠性工程师 (Site Reliability Engineer, SRE),专注于为 Google 的 ML 基础设施提供支持的系统。在这里,我认为这些挑战是真正复杂 (Complex) 的,因为需要新的范例和调度方法,尤其是在 Google 的规模上。

认识到系统是复杂 (Complicated) 还是复杂 (Complex) 真的非常重要。实际上,我们提到过复杂 (Complicated) 的系统从定义上来说是可重复的,而复杂 (Complex) 的系统则需要独特且定制化的方法。因此,如果我们尝试将一个通用的解决方案应用于一个复杂 (Complex) 的问题,它可能不会带来有效的结果

复杂系统的特征

在本节中,我们将讨论五个常见的特征,这些特征有助于识别复杂系统。并非所有复杂系统都具有每个特征,但它们往往至少表现出以下一些特征。

涌现行为 (Emergent Behavior)

当一个系统的整体行为 无法仅通过孤立地分析其各个组件来预测时,就会出现涌现行为。

例如,Gemini 产生意外结果 就是一种涌现行为。虽然我无法透露根本原因,但通过分别分析所有不同的组件几乎不可能预见到这种行为。

这是复杂系统的一个可能特征:它们的行为方式很难仅通过观察其各个部分来预测,这使得它们更难调试和管理。

延迟后果 (Delayed Consequences)

复杂系统的另一个可能特征是延迟后果,即行动 并不总是有立竿见影的效果 ,相反,后果可能只会在很久以后才显现出来。

例如,部署一个系统的新版本可能会引入一个微妙的问题,这个问题只会在几天甚至几周后才出现。这种延迟使调试变得复杂,因为与立即产生影响相比,识别根本原因变得更加困难。

在复杂系统中,仅仅依靠即时反馈会产生一种虚假的稳定感,当问题最终出现时,会导致巨大的意外。在这样的环境中工作时,记住后果可能需要时间才能显现出来至关重要。

局部 vs. 全局优化 (Local vs. Global Optimization)

在复杂系统中,优化一个部分不一定会改善整个系统 ,在某些情况下,甚至会使情况变得更糟。

与非复杂系统不同,在非复杂系统中,改进一个部分通常会导致积极的收益,而复杂系统则更难以理解。这些组件以不明显的方式相互作用,局部优化会产生难以预测的连锁反应,有时会导致系统层面的负面结果。

这突出了复杂系统的一个关键特征:整体大于部分之和。因此,局部收益并不总是转化为全局改进,在某些情况下,它们甚至会降低整个系统的性能。

滞后效应 (Hysteresis)

滞后效应描述了一个系统的 过去状态如何继续影响其行为 ,即使在原始原因被移除之后。

一个说明滞后效应的现实世界例子是交通拥堵:即使在道路交通事故被清除后,延误仍然存在,因为车辆仍然聚集在一起。同样,在分布式系统中,故障会导致级联的减速,即使在根本问题被修复之后也是如此。实际上,依赖系统可能需要时间才能恢复,原因有很多,例如缓存、重试或排队的请求。

在复杂系统中,仅仅修复根本原因并不总是足够的。因此,评估一个系统是否容易出现滞后效应,如果是,则预测其影响至关重要。

非线性 (Nonlinearity)

在复杂系统中,微小的变化会产生不成比例的巨大或不可预测的影响

例如,在排队论中,系统负载会以可预测的方式增加延迟。然而,当一个队列接近饱和时,即使请求的少量增加也会导致响应时间呈指数级飙升。

复杂系统经常达到临界点,行为突然转变,使得过去的趋势对于预测来说变得不可靠。这种非线性意味着传统的线性假设(即输入以可预测的方式映射到输出)对于设计、测试和推理复杂系统并不总是有效。

总结

为了总结本节,复杂系统:

请注意,仅仅规模本身并不能使一个系统变得复杂:即使是小型系统也可能表现出复杂的行为,如涌现或非线性。

驾驭复杂系统的模式

鉴于这些特征,我们如何在复杂的环境中有效地运作?以下是我个人发现有效的一些策略。

可逆性 (Reversibility)

在处理复杂系统时,我们应该尽可能地倾向于 可逆的决策 ,这意味着如果改变没有奏效,可以撤销的改变。

Amazon 的单向门与双向门框架很好地抓住了这个想法:

在许多情况下,尤其是在复杂系统中,倾向于双向门会带来更好的结果,因为我们可以进行实验、学习和改进,而不是预先进行过度设计。

也就是说,并非所有决策都应该是可逆的。例如,某些选择,如安全策略或与合规性相关的更改,需要预先承诺。关键是知道 何时优化速度和迭代,何时慎重和谨慎

跳出即时指标 (Think Beyond Immediate Metrics) 的局限

由于复杂系统并不总是对局部优化做出可预测的反应,因此定义 正确的成功指标 可能与我们所做的改变同样重要。实际上,过度关注孤立的局部指标可能会产生一种虚假的成功感,同时掩盖了系统中其他地方意想不到的负面后果。

为了避免这种情况,在进行更改之前,我们应该定义 局部和全局指标 ,以获得系统健康状况的整体视图。这确保了我们衡量的影响超出了立即关注的领域,并将系统视为一个整体。

精心选择的指标不应仅仅确认局部改变的成功;相反,它们应该帮助我们做出更好的决策,并确保在系统层面上实现有意义的改进,而不仅仅是孤立的领域。

创新 (Innovation)

正如所讨论的,复杂系统通常需要独特的解决方案。由于传统的策略可能并不总是适用,我们必须愿意 跳出框框思考并拥抱创新

我记得我在 Google 的第一次会议。有人提出了一个问题,就复杂性而言,尤其是在规模方面,这个问题似乎很荒谬。我脑海中立即的反应是:“这不可能 ”。但是,一位队友说:“但是我们是 Google,我们应该能够管理它! ”。

那句话让我印象深刻。虽然不是每家公司都拥有 Google 的资源,但我认为 心态才是真正重要的。当面对一个复杂的问题时,我们应该假设它是可以解决的,然后将其分解、实验和迭代,直到我们找到前进的道路。

有人可能会觉得本节很老套,但再说一次,复杂的问题需要非常规的思维。在许多情况下,当面对复杂的问题时,对创新解决方案持开放态度不仅仅是有帮助,而且是必要的。

受控发布 (Controlled Rollout)

在复杂系统中部署更改时,我们应该依靠经过验证的最佳实践来最大限度地降低风险。这些包括:

通过利用这些技术,我们减少了 故障的波及范围 ,提高了对更改的信心,并实现了更快的迭代。

可观测性 (Observability)

可观测性是 复杂系统的主要支柱之一。我对可观测性的工作定义(主要受到 Observability Engineering 的启发)如下:

您可以通过对高基数和高维度的遥测数据进行切片和切块来理解系统的任何状态(无论多么新颖或怪异),而无需发布新代码。

没有可观测性:

在不可避免地存在未知的复杂环境中,可观测性至关重要。它使团队能够驾驭不确定性,更安全地进行实验,并获得较短的反馈循环以持续改进系统。

没有适当的可观测性,改变仍然是观点,而不是知情的决定

模拟 (Simulation)

预测复杂系统的行为很少简单,有时,几乎是不可能的

我记得一个案例,我们花费了大量时间来设计一个改变,并用数据仔细地支持每一个假设。然而,由于未考虑到的因素,如潜伏变量,最终改变是无效的1

有时,与其仅仅依赖预测,更有效的方法可能是在推出更改之前 模拟 更改。有多种方法可以利用模拟测试,包括:

请注意,本节中介绍的想法也严重依赖于可观测性。

机器学习 (Machine Learning, ML)

在复杂的环境中,基于规则的方法通常会因为难以预测所有场景的复杂性而达到极限。在这些情况下,ML 会变得特别有效

实际上,与静态启发式方法不同,ML 模型可以根据反馈循环不断调整,并从真实世界的数据中学习,而不是依赖于严格的、预定义的逻辑。

这允许系统:

强大的团队协作 (Strong Team Collaboration)

最后但并非最不重要的一点是,我认为在复杂环境中,比在任何其他地方,强大的团队协作 都是绝对必要的。例如,清楚地传达为什么一个改变是复杂的,讨论可用的选项,以及与队友讨论权衡,都是至关重要的技能。

在复杂系统中,通常没有 唯一 正确的答案。因此,一个有效协作并共同应对歧义的团队可以产生巨大的影响,最终带来更强大的决策。

最后的思考

再说一次,复杂 (Complicated) 的问题可以用可重复的解决方案来解决,而 复杂 (Complex) 的系统则需要适应性和不同的思维方式。这就是为什么认识到一个系统是复杂 (Complicated) 还是复杂 (Complex) 如此重要:它塑造了我们应该如何解决问题。

然而,在许多环境中,系统既不是纯粹的复杂 (Complicated) 也不是纯粹的复杂 (Complex)。有些部分可以遵循结构化的、可预测的解决方案,而有些部分则需要适应性和新颖的方法。关键是学会认识到 何时需要适应性,何时结构化的解决方案就足够了

💬 我希望这篇文章能够帮助您识别复杂环境的特征,并为您提供有效驾驭它们的实用模式。这些模式中是否有任何一种引起了您的共鸣?您在复杂环境中还使用过哪些其他策略?请在评论中告诉我。