我曾经参加过一个后端职位的面试。技术栈是 Node.js 和 MySQL,很常见。面试官问:“如果你有一个包含一百万条记录的数组,如何按名字排序?”

我的第一反应是:如果你在 JavaScript 里真的维护一个一百万条数据的数组,那肯定是哪里搞错了。

面试官继续说:“你应该能根据多个字段进行排序。”

这听起来像是个陷阱题。正确答案显然应该是,解释为什么你不该在 JavaScript 里为百万级数据排序。分页、数据库索引、服务端过滤才是正解。所以我如实回答了。

但我错了,他想要听的是,用 Array.prototype.sort() 怎么实现。

我优先考虑现实世界的效率,而非戏剧化的规模,错了吗?为什么在面试官眼里,我不是一个务实的工程师,而是一个“缺乏远见”的候选人。

一、技术面试的戏剧性

我曾读到一句话:“复杂的系统往往反映的是缺乏良好的设计。”这句话很精彩,也很真实。但如果你要准备系统设计面试,立刻把它忘了。

在真实的程序世界里,简单为王。而在面试里,复杂才是货币。

工作面试并不是评估,而是一次职位试镜:角色是“能解决所有复杂问题的架构师™”。

二、潜规则剧本

每一次系统设计面试都遵循同一套戏剧公式:

第一幕:召唤巨龙
先假设有无限用户和全球流量。把一切合理数字放大 1000 倍。把一个待办应用当作是纽约证券交易所。当你描述这款本质上是数字记事本的产品拥有数百万并发用户时,面试官会赞许地点点头。

第二幕:绘制符文
然后在白板上画满方框和箭头,至少要有一个冗余的 Kubernetes 集群。必须加一个消息队列,最好是 Kafka,不管用不用得上。撒上一点微服务,因为单体是“落后者”的选择。每个组件都要用负载均衡器当护身符保护。

第三幕:祈求技术之神
最后,你要为博客评论系统讨论一致性算法,顺带提到可观测性和 SLOs,再轻声念一句“最终一致性”,仿佛能驱走未来所有扩展性问题。

这场表演和实际工作毫无关系,它只是证明你会说大量专业术语。

三、面试世界 vs 真实世界

面试世界:复杂 = 能力

  • 展示对分布式系统模式的熟悉
  • 熟练掌握企业级工具
  • 能为“虚构的百万级用户”设计合理的架构

真实世界:简单 = 好设计

  • 从最简单可行的方案开始
  • 仅在确实需要时才增加复杂性
  • 为可维护性做优化,而不是假想规模

我见过优秀工程师在面试中失败,只因为他们提议用关系型数据库而不是分布式 NoSQL 集群——即便系统每天只有 100 个请求。

我也见过平庸工程师被录用,只因为他们能流利讨论“分片策略”,哪怕问题根本不需要。

四、戏剧存在的原因

这并非恶意,而是结构性问题,由多个因素驱动:

  • 信号 vs 噪音:复杂性比判断力更容易评估。任何人都能背 CAP 定理,能区分 SQL 和 NoSQL。但要判断何时不该用分布式系统,在 45 分钟里很难考察,于是面试官倾向于能量化的东西。
  • 规避风险:招聘委员会更怕“错过好人”,而不是“招到坏人”。“简单”答案显得冒险——万一此人真不能应对复杂场景呢?复杂答案更保险,哪怕完全是过度设计。
  • 理想化差距:公司往往为自己“理想的未来”招人,而不是当下的需求。他们想要能“支撑百万用户的高级工程师”,而不是能写好“10,000 日活用户代码的开发者”。未来规模的幻想决定了今天的招聘。
  • 面试官激励:讨论负载均衡和一致性协议,比 CRUD 有趣得多。即便 CRUD 才是工作里 90% 的内容。面试官也是人,人类更喜欢有趣的对话。

一旦入职,剧本就完全翻转了。你每天要删除“为未来规模准备”的没用微服务;要反对本该用 cron 就能解决的问题里乱加消息队列;要合并“为可扩展性拆分”的数据库。你得不断告诉热情的新人工程师:新功能真的不需要单独的 Kubernetes 命名空间,有时候一个简单的 bash 脚本比分布式系统更可靠。

让你被录用的复杂性,最终会变成你几年都拆不完的技术债。我曾与一些工程师共事过,他们在系统设计面试中凭借繁复的架构方案轻松过关,但入职后的第一年却都在简化系统——那些系统正是前人基于同样的面试逻辑过度设计出来的。由此形成了一种循环:先制造复杂性,再拆解复杂性,而这一切完全是面试戏剧所驱动的。

五、诚实的代价

如果你在面试中尝试务实,会发生什么?

  • 背压问题:“你在系统中如何处理背压(Backpressure)?”
    • 诚实回答:“我们根本没有那么大流量,不需要背压机制。”
    • 面试回答:“我们实现带断路器和队列深度监控的指数退避。”
  • 数据库问题:“这个用例用 SQL 还是 NoSQL?”
    • 诚实回答:“Postgres 完全能处理,而且团队都懂 SQL。”
    • 面试回答:“我们会采用多元持久化策略:Redis 缓存、Cassandra 存时间序列、Neo4j 做社交图谱。”
  • 扩展性问题:“你如何处理 1000 万用户?”
    • 诚实回答:“我们没有 1000 万用户,只有 1 万,先解决这个。”
    • 面试回答:“我们会用一致性哈希的水平分片和自动扩展的 Kubernetes pods。”

诚实答案体现的是经验,面试答案体现的是词汇。你猜哪个更容易拿到 offer?

六、如何赢得这场游戏

我并不是提倡虚伪,而是承认现实。面试是一种仪式,仪式有规则,需要我们去应对它:

  • 区分表演与实践:玩转面试游戏不代表虚伪,而是对破碎体系的务实态度。你可以在面试舞台上“演戏”,入职后依旧做一个有技术原则的工程师。

  • 学习“圣典”:即使用不上,也要研究分布式系统模式;即使无关工作,也要记住 CAP 定理;要练习画那些在白板上看起来很厉害的架构图,这就像学习一门只在面试时使用的外语一样。

  • 拥抱套路:总是以“在规模化情况下,我们需要考虑……”开头。无论系统大小,尽早多提监控和可观测性。处处加冗余,即使对非关键组件。说出那些面试世界里“象征能力”的魔法词。

  • 然后摘下面具:一旦入职,就要毫不妥协地追求简单。勇敢地质问:“我们真的需要这些复杂性吗?”用在面试中积累的“信誉”去抵制过度设计,这才是真正的程序世界。

七、尾声

这个体系虽然令人沮丧,但不是永恒的。已经有一些公司开始意识到问题,并尝试新方法。他们给候选人提出的是真实问题,而不是假想的规模化挑战;他们奖励质疑复杂性的工程师,而不仅仅是能实现它的人;他们要求候选人识别现有系统的过度设计,而不是创造新的复杂性。

但在这些实践普及之前,我们依旧被困在剧场里。它满足了太多心理需求:让面试官感觉聪明,让公司显得严格,让候选人觉得自己在解决大问题。技术面试存在于一个平行宇宙,规则完全不同。舞台需要复杂性的表演,而工作则奖励对简单的掌控。

系统是破碎的,但个人无法靠牺牲去修复。扮演好角色,拿到工作,然后利用你的地位推动改变。

记住:目标不是永远维持戏剧,而是进入大楼,然后让别人看到皇帝的分布式微服务其实没有穿衣服。

对面试的戏剧性最好的反击,不是拒绝表演,而是表演成功。然后,你就能用整个职业生涯去删除它所歌颂的冗余复杂性。