历时近两个月的面试终于告一段落,终于有时间整理下自己这次的换工作心得,分享给大家。
面试经历
我的基本情况是这样:中下等 985 学校本科毕业,非计算机专业,在北京工作五年,之前一直在中小私企、国企工作。虽然学历还可以,但是技术谈不上精湛,只能说知识面还可以,技术栈广而杂。毕业以来薪资一直不太满意,尤其是上一份工作,在一个新创建的国企工作三年有余,薪资一直几乎没有变动,停留在不高的水平。刚入职的时候觉得还好,虽略低于同学但是好歹不忙,平台也不算太小。但是三年没有变化,做了诸多努力也无力改变现状,于是渐渐的有了离开的想法。
最终结果还算比较理想,如果把 offer 的岗位分为两类,好岗位是个人喜欢或者比较核心的业务,一般岗位是个人不太喜欢或者边缘业务,我一共拿到了以下 offer:
- 小米好岗位
- 京东一般岗位
- 美团一般岗位
- 跟谁学好岗位
- 百度一般岗位
- 快手好岗位
- 微博好岗位
其他挂掉的大厂还有:滴滴一面挂、字节二面挂、猿辅导一面挂、完美世界一面挂。
拿到的 offer 总结来看,小米跟谁学薪资稍低,京东美团百度虽然都是知名大厂,但是业务方向或者边缘或者自己不喜欢,就放弃了。最终在微博和快手中抉择,二者都是比较核心的业务,自己也挺喜欢两家公司,基本薪资也差不多,跟之前比基本实现了 double。但是考虑到快手的福利更好,而且现在正在快速发展期,最终决定去快手。
另外多说一句,虽然经常见到 HR 提到 30% 的涨幅上限,但是只要你 base 很低(比如在下,都是泪),或者面评给力且有其他 offer 拿来谈价格,涨幅并没有这么死板。常见的互联网三大抠也没压我的涨幅(可见之前有多低…怨念)。
而挂掉的几个,事后复盘的话,基本是自己准备不足,细节问题没回答好。滴滴除外,它比较有意思。我感觉回答的还不错,跟面试官谈的也挺融洽,最后聊工作职责的时候,年纪不大的面试官跟我用略有抱怨的语气说其实技术不复杂,但是业务很啰嗦,对个人成长没那么大帮助,一脸劝退的样子,然后就把我挂了。哈哈哈感觉还挺有趣的人,是友善的帮我避免踩坑。
基本思路
我总结了面试的几个基本思路:
- 打好基础,技术不好啥都白搭
- 调整心态,面试其实很看运气,即使你再牛,也很难说百分百能面过某家公司
- 步步为营,先易后难,把小公司、不那么想去的公司放到前面练手 + 拿 offer 用来抬薪
- 及时复盘,总结经验,多多投递
一、打好基础
首先我自己的战线其实很长,开始也说了,我的技术远远谈不上精湛,多数只是用,对原理不了解,但是这次准备的相对比较充分。
从去年萌生了离职想法之后,开始是先在公司内部做了一些努力,无果。十一二月份坚定了想法,开始准备,把市面上常见的面经、题纲都了解了下,然后逐一学习,Java 基础、MySQL、框架、Redis 等等这些都是重中之重,这里不详细说了,下面技术栈章节再说。从开始准备的时候,我就大概估摸了一个学习的时间,给自己定了个目标,就是大概半年,下定决心在五六月份开始面试,然后倒排制定计划。
然后就是努力学习,我工作不忙,多数时间六点半就能到家,然后除了吃饭洗澡之外基本都在读书记笔记写代码和刷 leetcode,因为本来就夜猫子,而且心里憋着口气,基本能学到晚上一两点,就这么坚持了半年。
二、调整心态
心态非常重要。我自己的心理承受能力其实很差,而且很容易紧张,但是基本的道理心里还是想清楚了。
首先面试就是在短短的几个小时里判断一个人的技术能力和基本素质,所以其实并没有太准确,很看运气。有时候就算你技术很好,面试官就是跟你不一个频道,也是白搭。所以心里一定要记住这一点,不要计较。
其次不要把目标定的太狭窄,比如非哪里不去。东方不亮西方亮,有时候一个公司不行,不一定是自己的问题,总结总结经验下一场就有可能碰到聊得来的面试官。
不过话又说回来,其实大公司内部也有众多部门,就算你非常想去某个公司,一个部门没面上也有机会面别的部门,我就见过一个老哥面了四次字节跳动,前三次都挂了,然后又被捞起来三次,最终如愿以偿。
所以机会非常多,一次成败不要放在心上,好好准备就行了。
三、步步为营
关于投哪里,我是这么做的:先根据自己的能力,定一个大概的上限,然后根据自己的接受程度,定一个下限,分开层次,从低到高依次投递。前面的过不过的无所谓,反正过了也不去,就当练手了。等手里有几个 offer,并且状态正好,面试也不怕了,掌握不太精确的技术点也补上了,就开始投最终的几个理想公司。以我个人为例,这次是打定主意去互联网公司了,所以就把市面上的大厂按照规模、认可度等等把想去的公司列了个表分了个级别,从高到低依次是:
- 腾讯、阿里、字节、快手(这些最想去,或者规模大技术强,或者风头正盛薪资福利好)
- 滴滴、美团、华为、微博(次顶级大厂,认可度高,薪资主流)
- 百度、京东、网易、小米、猿辅导(前面其实也都是二线大厂,只是个喜好原因往后排了下,猿辅导脱引而出是由于薪资实在太高)
- 其他二三线互联网公司
最后的结果,里面的公司除了华为全员 OD,网易忘了投,腾讯没找到合适岗位,其他都投了一圈。另外还投了几个不知名互联网公司练手。随着面试次数增加,面试越来越熟练,技术上也查缺补漏,所以总的来说是越来越顺利的。另外由于是一个接一个的面试,每次谈 offer 的时候都可以讨价还价下,最后的 offer 总包也比第一个高了七八万。
四、总结经验继续努力
一两次的失败并不可怕,我前几个投递的小公司也不太理想,确实打击了一点自己的自信心。但是也有好的方面,我知道了自己薄弱的环节,比如缓存处理、数据库分库分表这些东西之前用的比较少,没想到面试问得很频繁,于是我赶紧补充这些知识,不说多深入,至少能应对一些简单问题免得面试尴尬。
就这么一路面试下来,自己不会的知识点也会越来越少,熟悉的东西越来越多,跟面试官就能愈加流畅的沟通,面试评价也越来越好。
技术栈
其实常见的面试技术栈网上已经很常见了,这里我再重复一遍,然后补充自己在面试中频繁遇到的问题。
面试中问的技术问题大致上可以分为三类:
- 知识点
- 数据结构和算法
- 系统设计
由于已经工作五年,所以重点考察 1、3 两部分,对算法考察反而要低于应届生,基本都是常见问题。
对于面试中的问题,在准备的时候要注意,首先是要记忆准确,不要模棱两可。另外一定要举一反三,复习一个知识点的时候想想他的应用、扩展、原理、优劣势等等。
然后面试的时候会的就说,不会的不要含含糊糊,不会的时候硬答会大大的减分。一般遇到我不会但是有点思路的问题,一般都这么说:“我不确定实际是怎么实现的,但是在我看来可以 xxxx”,至少告诉面试官你的思路。其他题目也是这样,比如算法题开始做之前一定先跟面试官沟通,问清楚边界条件,然后先给面试官讲讲自己的思路,他认可你的思路之后再开始写,这样即便最后不能 bug free,他至少也知道你有思路,也避免了提笔写半天结果方向错了。而对于系统设计题,不会的话也可以找共同点,关联到自己会的地方。比如有一次面试官问我大并发下的计数,我正好看过 LongAdder 的源码,就拿出来讲了讲,二者虽然不完全相同,但是思路类似,也正好展示了自己其他地方的知识点。
一、知识点
直接列知识点好了,下面写的比较笼统,更详细的内容应该网络上非常多,准备的时候一定要深入,比如线程池,就有面试官问我创建方式、参数含义、启动过程、内部原理等等,更深一点可能会问你为什么这么设计,有什么优劣。
- Java 基础:考察 Java 集合、并发包工具、多线程、线程池、并发相关的关键字、锁和锁升级。
- JVM:内存模型、常见 GC、不同 GC 之间的区别、GC 流程。有的会问的更详细,比如 CMS 是以最短停顿时间为设计目标,那么它怎么实现这个目标?G1 以可预测的停顿时间为设计目标,它怎么完成这个目标的?
- MySQL:数据存储结构、索引、锁、事务、MVVC、性能优化、高可用方案。MySQL 的确非常复杂,可以问的地方非常多。比如索引,哪些情况下索引失效,联合索引怎么用,什么原理一定要清楚。但凡有多种模式可以选择,一定要想想优劣对比。比如 InnoDB 引擎和 Myisam 引擎的区别,binlog 中有 Row 格式和 Statement 格式,二者有什么区别,为什么这么设计。
- Redis:Redis 问的是真的多,首先他应用广很多企业都用 Redis,其次它代表了计算机领域一个大的基础问题:缓存,可以考你的点很多。Redis 的数据结构、底层结构、持久化方式这些是基础,然后很可能会结合实际情况,问你怎么用 Redis 的,用到了哪些数据结构,为什么这么选。然后的话是缓存同步的方式。这里我整理了一篇常见的缓存处理方式总结:缓存系统常见问题总结
- 框架:Spring 反而考的不多,可能是满大街都是了。问我的基本就是循环依赖、生命周期、AOP 原理,还有像 ApplicationContext BeanFactory 区别这种问题。然后 Mybatis 可能会问下一级缓存二级缓存。
- 消息队列:消息队列也是非常常用的组件,面试中也问的比较多。主要包括消息丢失、重复投递、保证有序这三种问题,要清楚实现原理。然后要了解消息队列本身的架构、高可用部署方式。
- 网络相关:HTTP、TCP/IP、七层网络模型等等基础知识点。然后 Netty 和 NIO,搞清楚 select poll epoll 的区别和联系。
以上算是最常用的技术栈吧,根据不同公司,还有每个人简历的不同,我还遇到的一些问题包括:
- 容器相关:Docker 和 K8s,一般问点皮毛和应用,毕竟也不是做这个方向的。
- 前端:可能会问些 http 协议、跨域等等跟前后端都相关的问题,毕竟后端岗位,不太会问纯前端的问题。
- 微服务:Spring Cloud、Dubbo、Service Mesh。由于我做微服务很少,所以面试中也遇到的不多,最多就是问到 Hystrix 的熔断和其原理,还有调用链路的问题定位、监控等等。
- Linux:基本就是看看你是不是实际用过 Linux,常见的 top、free、iostat、nload 等查看服务器各种状态的命令,然后就是遇到两家问我文本处理的脚本,像“输出 access.log 中频次最高的 100 个 IP 地址,去重排序后输出”,虽然做了准备但是平时很少有,现场没写出来…
- 分布式系统相关:几种分布式锁和要注意的问题,分布式一致性协议 Paxos、Raft 和 ZAB、Zookepper 的数据结构等等。然后就是分布式事务,2PC、3PC、TCC。
二、数据结构与算法
首先这一部分也是我的弱项,而且由于已经毕业五年,虽然基础也会有考,但是大多数公司的门槛都会比较低,这么多家公司面试过来,基本都是问的 leetcode 中 easy 和比较基础的 medium 级别的题,仅仅在面百度的时候遇到了一道 hard,但是我没给出最优解,给出的解法只能算是 easy,同样也让过了。
具体应该准备哪些部分,在 github 上或者知乎上也有比较详细的指导教程,我就不详细叙述了,仅仅根据我面试的几家经验,认为可能会比较基础、常考的内容包括:
链表、二叉树、简单的字符串、栈、滑动窗口,递归比较容易解的题目要能写非递归解法,深度搜索广度搜索,简单的回溯等等。
另外我个人着重准备了一些动态规划的内容,因为觉得很难,但实际上没怎么考。
基础的集中排序算法要心里有数,能记住空间和时间复杂度、稳定性。
然后就是训练量啦,我本人也做的不多,就刷了两百多道,感觉一般的公司还能应付,就是面字节的时候的确压力大一点…
三、系统设计
之前海外学子准备面试的时候讨论比较多的,感觉现在国内也渐渐重视起来了。常见的系统设计题目网上也有很多,不再赘述,但是由于这类题目往往比较开放,很可能不会问到你准备好的原题,所以一定要理解思路,掌握常见的设计技巧,沟通清楚题目要求和条件。而且系统设计没有优劣,只有合适不合适,所以一定要根据业务需求来,讲清楚自己的设计有什么优点,适合什么场景,有什么缺陷,在什么场景下不适用。
然后的话就是日常积累,比如我知道的像 infoQ、掘金等网站经常会有设计类的文章,将某某公司的某些技术,或者某些极端场景的解决方案,然后有些论坛、社区也时常会有人讨论,见多识广之后,这类题目一般也了熟于胸了。
然后前几天正好整理了一个简单的系统设计面试题总结,其实是自己复习的时候用的,比较简单,仅做参考:常见的架构设计面试题
结尾
以上就是我最近半年从准备到面试的过程、技巧还有思路总结啦。学习是一辈子的事情,除了一些面试的方法策略,更重要的还是平时的日积月累,主动学习。
最后祝愿大家都能拿到自己满意的 offer。