这篇文章对很多没有高并发经验的程序员来说,会非常有帮助。
很多程序员可能都遇到过类似的困惑:
我没有高并发项目经验,但是面试的时候经常被问到高并发、性能调优方面的问题,该怎么办?
这个问题怎么解决?和大家说说我招人的一个经历。
程序员小张参加工作已 5 年,是一位高级工程师,是我亲自招进公司,表现很出色。
前一阵子,我把小张叫进会议室,想让他单独带个团队。其中,我谈到了面试时,他简历注水的问题。
事情是这样的,大概两年前,公司有个核心项目缺人,需要一位高级程序员。这个岗位非常重要,所以对面试人要求不低:
- 有高性能、高并发开发经验
- 有高可用系统经验
- 参与中间件研发、优化和系统存储优化
招聘持续了两个月,面试了许多工作五年以上甚至十年的人选,却依然没有招到一个特别合适的。
就在我们快不抱希望的时候,同事让我去面试一个有趣的人,他强烈推荐,并顺手把简历递给了我,这人正是小张。
接过简历后,我先翻了翻。这一翻,让我皱起了眉头。
简历里,小张的工作经验只有区区三年,这三年全都在一家公司,公司本身还没有什么名气。
更重要的是,我怀疑他的简历做了手脚。
他说自己三年里,负责过两个项目,一个是电商项目,一个是关于这个电商项目的对外开放平台。对这两个项目,他着重强调了项目的高并发,并说自己解决了很多技术难题。
就是这里出现了问题。我们当时也有电商项目,市面上稍微有点名气的电商平台我都非常清楚,却没听说过他简历里的产品。所以我怀疑,这份简历是包装过度了。
但是,对于这么明显的问题,我不信前面的面试官们都没看出来。那么,为什么他们还推荐我去见见呢?
说心里话,对简历包装过度我是比较恼火的,但是这只是我的怀疑。同时,前面的面试官竟然是带着一种从未有过的满意语气,叫我一定面面他,对同事们的认可我又比较好奇。
就这样,我带着恼火又好奇的矛盾心思见到了小张。
见到小张的时候,我由于有点恼火,脸色显得非常严肃。他可能看到我如此严肃,不禁局促了起来。但是,从他的眼神中,我又看到了很强的自信。我心里想,确实挺有趣的人。我决定要好好的面试下这个人,看看他到底有什么本事,能让我的同事如此满意。
问了下他大概背景后,开始了进入了正题。当进入了正题之后,小张的回答态度就让我大加赞赏。态度自信,不卑不亢,逻辑表达也十分清晰明白。
这时候,我心里决定,如果小张后续的回答,能证明他的实力达到简历描述的八成水平,我会倾向于把 offer 给他。
我先问了问他对高并发的理解,比如
高并发需要参考哪些指标?
他告诉我,高并发由于产品类型不同,所以指标都不一样。以他负责的电商系统来说,根据模块的不同,关注的指标不同。商品浏览看得是 QPS,订单模块则是看得 TPS。同时,他们还需要关注活跃的用户量等等。
这回答真不错。面试以来,哪怕是工作多年的人,绝大多数的答案就是 QPS,无非再多一个 TPS。能把产品类型的不同和不同的高并发指标之间关联起来,这说明小张是仔细对这个问题思考过的。
我愈发满意了。在后面,我又追问了集群部署、多级缓存、复杂查询优化等有关性能优化的问题,还附加了系统高可用的各种策略,和如何拆分去保证灵活扩展等实际中我们正在采用的问题。
等面试完毕后,时间已经过了一个多小时。小张当时并没有百分百答好我问的问题。
从实际回答来看,关于性能优化的细节,比如,系统瓶颈的检测和优化,程序逻辑的优化,JVM 优化甚至数据库的优化都答得异乎寻常的出色。
但是,对于高可用的大概策略,比如降级处理,限流处理等,他只知道大的方向,很多答案一听就知道是从书本上或者互联网上看来的。
而对于系统的扩展性相关问题,他甚至答的非常差,很多都回答不上来。
不过瑕不掩瑜,小张依然拿到了 offer,他期望的薪资我也没有打任何折扣,这足以给他一份大大的惊喜了。
在后来的两年里,小张的出色表现,证明我没有看错他。
他为了公司的核心项目做出了巨大贡献,而他的技术水平,也有了肉眼可见的巨大提升。他成为了一名高并发经验丰富的高级程序员。所以,现在打算让他带团队了。
“那么,就剩一个问题了。你面试之前到底是如何做到熟悉高并发的性能优化的?” 我好奇的问出了我压在心底的问题。
小张不太好意思的挠了挠头,他详细给我讲述了他是如何搞定高并发经验的。
我听完后,真的是对他这些准备赞不绝口。我认为该分享出来,让更多的人看到。
划重点!如果你也渴望有高并发经验,那么下面的内容你要格外关注了。
小张确实是做了电商平台开发的。但是,这个电商平台没多少访问量,QPS 可能一只手都能数的过来。说句难听话,也就是挂在网上而已。
他刚毕业入职开始,就参与维护了这套电商平台。就这样持续了一年后,他发现自己已经无法再有任何提高了。
他想跳槽,但是发现很多高级岗位都是要求高并发经验的,他对此很着急。如果他继续在以前的公司发展,就势必接触不了什么高并发。但是跳槽的话,他又必须有高并发经验才能找到一个不错的岗位去继续提升自己。
这貌似成了一个死结。
在百般无奈之下,他决定自己模拟高并发去获得经验。
现在总结下来,其实他的练习可以粗略分为三个阶段:
第一阶段
这个阶段,小张完成了在高并发条件下,对单机性能优化的学习。
小张用 Docker 容器去运行他维护的电商项目。然后用 jmeter、wrk 等工具去压测。
在压测期间,他敏锐地发现了由于系统每个模块不同,所以性能表现就不一样,这种现象引发了他的思考。他经过网络搜索和查询资料,明白了不同模块、不同产品对并发指标的要求是不一样的。
基于这种情况,他又根据产品的业务逻辑编写了复杂的压测脚本,能自动实现不同模块的压测任务。
就是在这种不断地压测探测下,他明白了如何探测问题,如何通过优化代码、JVM 去解决问题。
比如,解决误用 HashMap 导致死循环的问题。又比如,误用不带缓存的文件 IO 流,去读取文件的问题等等。
在程序和 JVM 优化完毕后,他又发现数据库也存在问题。于是,他又学会了如何优化数据库 SQL,如何对数据库分表等问题。
也是在这个阶段,他认识到了缓存的必要性以及同步缓存数据状态的重要性等重要知识点。
小张在搞了单机优化后,他觉得也没有办法再通过单机的压测学到什么新的东西了。于是,他转向了第二阶段。
第二阶段
小张从阿里云买了两台机器,他开始尝试使用负载均衡去分担高并发的压力。
同样的,也是借助压测工具去模拟了高并发。在压测期间,负载均衡和系统屡屡出现和单机完全不一样的问题。
比如,负载均衡本身的性能问题。比如,在一些时候,负载均衡后面的机器负载是不平衡的,需要对负载算法进行调整。
这个阶段,小张理解了负载均衡中大部分的细节。
但是,高并发中,很多系统的构成会很复杂,以至于需要分布式架构系统的程度。他们需要各种中间件做通信,做存储。
所以,小张根据招聘的一些需求,他做了第三阶段的练习。
第三阶段
为了能熟悉市面上各中间件的使用,小张把他那套电商平台改了又改。
比如,一些本地调用的方法,被他替换成了 Dubbo 远程调用。比如,一些模块间调用,被他替换成了 MQ 中间件传消息。再比如,一些放在关系数据库的被频繁访问的数据,被他改存在了 MongoDB 中……
当然,压测依然继续。就这样,小张又实践了很多中间件和分布式框架的使用。
在模拟高并发练习的同时,小张不忘去读各种高并发高性能的书籍。比如,《大型网站服务器容量规划》、《互联网创业核心技术:构建可伸缩的web应用》等书籍。
在来到我们公司面试之前,小张如此练习了两年左右。
虽然小张面试的时候表现也存在很多不足,但是我当时看中他的一些优点是:
1. 小张满足具有高并发经验的要求
为什么我们需要找有高并发经验的人?
说白了,我们想找的程序员其实是:
- 不会乱写性能很差的代码
- 能敏锐感知到影响系统的问题
- 能独立的处理由于高并发引发的问题
小张通过他的练习是掌握了这些技能的。
2. 小张满足熟悉高可用的要求
我们找熟悉高可用的人,其实并不要求这个人一定能给出什么独特的高可用方案。我们要求的是,他能知道高可用的知识后,去意识到高可用的重要性。
比如限流功能出现问题,他要能马上认识到这是个很重要的问题,从而把解决的优先级提到很高。
小张通过学习,明白了高可用的重要性,也知道了高可用的大方向,这就够了,剩下的细节,我们有信心带小张在实际工作中学出来。
3. 小张能参与我们的中间件研发和存储优化
小张主动改造过他们的电商系统,而且使用了很多的中间件,并对这些中间件都进行过优化。对这些中间件的特性比较熟悉,并且在实践中,他也了解了很多原理。
除此之外,小张的主观能动性尤其打动我们。他对技术的主动钻研、主动学习,表明了他是一个喜欢走出舒适区,愿意挑战自己的人。而这样的人,有哪个团队不欢迎呢?
所以,其实没有高并发经验并不可怕。
如果在工作中你接触不到高并发的项目,那么也没必要太纠结。公司做什么项目你改变不了,你能改变的只有你自己。关键还是自己要去主动学习,主动练习,主动提升。只有这样的人,机会才会去垂青。
最后,毕竟在程序员这个圈子,90% 以上的人可能都没有真正的高并发经验,所以在此也希望各位面试官,在招人的时候,如果遇到好苗子可以适当宽容一些,给新人们一点机会,说不定能找到一匹千里马。