海龟龟

国内互联网软件工程师面试风格

背景介绍:在国内互联网公司,软件开发至少分为工程(SDE)和算法(MLE),工程又至少分为客户端(frontend)和服务器端(backend)。本文依据我们在2020年底亲历的技术面试,主要针对2-3年工作经验的服务器端工程导向岗位,因此可能与其它工作年数和工作方向的面试风格有所出入。

概述

国内互联网公司的面试风格与美国大厂有比较大的区别。美国大厂的面试基本分为三项:算法、系统设计和文化。而国内公司考核的内容更广泛和随机,一场典型的面试可能是这样的:先写个算法题热热身,然后问问简历上的一个系统的架构和某个技术细节,接着让设计一个接近但略有不同的系统,随后聊聊Java并发容器的实现思想,最后谈谈一些常用组件的实现原理。它涵盖了技术面试的五个考核重点:

  • 算法题
  • 系统设计
  • 简历上项目的技术细节
  • 组件原理
  • 基础知识

下面我对每个考核方向进行介绍,并提一些或许有用的建议,但我不会回答“为什么国内公司要考察这些”——这是个好问题,但我没有明确的答案。

算法题

美国大厂在招聘0-3年(甚至更长)工作经验的工程师时,面试的重中之重依然是算法题,这很大程度上是受谷歌的影响。我插播一个来自Blind(美国版脉脉)的经典帖子,让大家感受一下这种面试模式给社会带来的深远影响:

My gf dad is principal engineer at Msft. It was dinner time. We started with casual conversation about tech jobs and stuff. From there we started talking about interview process and out of nowhere he asked me how i would solve an array question. He acted like it was casual conversation but I could see how he was evaluating my answer. Initially I was taken back a little but then I got hold of my senses. After all I have years of LC experience. This was day to shine. I started answering with brute force solution followed by optimal solution. Talked about time and space complexity. In the end he was somewhat satisfied.

They are asking us to visit again during Christmas break. I wonder if I should prepare for system design.

与美国大厂最大的不同在于,算法题只是国内互联网公司面试的一部分甚至一小部分。除了这一点,二者在题目难度和考核形式上都相似。

在面试准备上,我有两点建议。首先,可以适当练习,保持熟练度,但不应该只准备算法题,而忽略了其它部分的准备。我在与美团和快手的面试中,算法题都只占整体考核内容的三分之一以下,且没出现难题怪题。当然不排除有公司整体更喜欢考算法题,但我没经历过只考算法题的国内大厂。

其次,因为国内公司同样要求候选人线上编码+执行,依然可以使用LeetCode进行练习。至于是使用英文站还是中文站,则区别不大。略有区别的地方在于,中文站能反映题目在国内公司面试中出现的频率,更具有代表性;英文站则沉淀了大量的优质答主(例如Stefan Pochmannlee215)的解法。

系统设计

国内公司跟美国大厂的问法也比较接近,例如设计一个微博,设计一个API限流。大致有两点区别:第一,系统中涉及到一些组件(例如Redis)时,面试官通常会考察一下候选人对组件原理(见下文)的了解。第二,问题会涉及到一些在国内互联网生态中比较常见、而在美国比较少见的场景,例如秒杀。

在面试准备上,我参考了System Design Primer,并额外准备了秒杀这样的场景。

项目技术细节

在介绍项目时,尽量往契合岗位的方向去引导。例如,如果自己有广告后台的经验,且面试的岗位就是广告后台,则应突出相关经验,准备好项目的架构、细节以及所使用组件的原理(见下文)。如果岗位和经历不是特别契合,可以尽量在简历上体现项目所用到的技术栈,例如缓存、消息队列等,这样子方便面试官提问,也方便自己准备,利人利己。

对于项目的技术细节,尽量做到知其然,也知其所以然。例如,这个模块的缓存为什么选用这个Redis?为什么没有选用Memcached?为什么没有在应用层面做缓存,而选择引入一个服务依赖?选用了哪个Redis的客户端,为什么?

组件原理

一般来说,美国大厂极少考察这种问题。我认为国内公司考察这类问题有两个目的。第一,考察候选人对常用技术的熟练度,期待候选人在入职后能尽快上手。第二,看看候选人有没有对技术的好奇心。

缓存(例如Redis)、数据库(例如MySQL)和消息队列(例如Kafka)本身比较基本和常用,就算简历上没专门写,也可能会被问。如果只了解相似组件,也没问题,不会Redis也可以谈谈Memcached,不会MySQL也可以谈谈PostgreSQL,不会Kafka也可以谈谈RabbitMQ。除了这些常用组件,简历中提及的组件也会被考察。但如果既不基本,又没有在简历中写,正常情况下是不会被问到的。

在考察组件原理时,大致有两种风格。第一种是直接问细节,期待得到一个比较规范的答案,体现候选人对组件的熟练度。例如,对于Redis,面试官可能会问出下面这样的问题:

  • Redis支持的数据结构有哪些?
  • Skiplist如何实现?Redis为什么使用skiplist?
  • Redis支持怎么样的事务,如何支持?
  • 如何用Redis实现分布式锁?

第二种风格是让候选人谈谈某个组件。此时候选人发挥空间更大,我建议可以大致按以下顺序谈论:

  • 组件解决的问题。
  • 给开发者暴露的接口。
  • 组件的实现原理,比如关键的数据结构、算法、架构、工程优化等。
  • 结合自己的项目实践,阐述组件在解决特定问题方面有什么优势。

值得注意的一点是,美国云服务成熟,因此美国科技公司(无论大小)都大量使用云服务。这些服务大致分为两类:

  • 基于开源软件的托管服务,例如AWS RDS。
  • 闭源,例如 AWS Kinesis、AWS SQS、AWS DynamoDB、Google Cloud Spanner、Datadog。

对于闭源的,在实现原理部分,可以事先了解并向面官介绍paper、相近开源实现,避免用一句“闭源的不了解”而让空气突然安静。比方说,如果面试官让你介绍一下项目中使用的AWS Kinesis,不妨聊聊Kafka。

基础知识

与“组件原理”类似,只是问题的领域有所不同。我就直接举一些例子吧:

编程语言,例如:

  • Go Channel如何实现(如果你平常写Go)
  • Java ConcurrentHashMap如何实现(如果你平常写Java/Kotlin/Scala)

网络,例如:

  • TCP的三次握手和四次挥手的细节,和为什么
  • HTTP1和HTTP2的区别
  • HTTP和RPC的区别

操作系统,例如:

  • 进程和线程的区别

面试小技巧

主导面试。由于算法题的占比较低,因此候选人和面官有很多讨论其他问题的时间。我建议在讨论的过程中,通过针对性的准备,引导面官在你熟悉的领域提问,进而体现自己对技术的熟练和热情。面试官通常也乐于见到你对某些话题的专长。因为他们并不是很在意你不知道什么,而是更想知道你会些什么,能给团队带来什么样的补充。

知己知彼。由于语言环境的不同,中美软件工程师的词汇有些区别,可能会出现一下子没听懂的情况。例如,海外同学可能不明白服务编排等同于microservice orchestration,反之亦然。为了解决这个问题,我选择阅读一些国内大厂在相关领域的技术文章,例如伴鱼技术博客美团技术博客。这既能帮助我快速对齐术语,也能对国内业界的实践有一个具体的认知,这两点都很好地帮助了我的面试。

总结

中美科技公司在面试风格上差异较大。美国大厂特别注重算法题,对特定技术栈通常不会有要求。国内公司更期待候选人在能写算法题的基础上,对计算机基础有一定了解,对技术栈较熟悉。想找国内公司工作的海外同学,需要做针对性的准备。

2赞