阅读本文大概需要 5.6 分钟。
作者:翟洪毅
一、梦想和被拒
二、积累
三、结语
首先介绍一下投稿作者 翟洪毅,16年华理计算机本科毕业。在年前拿到了蚂蚁金服Java开发的offer,P6。
工作经历:
15-17年,壹钱包实习、工作,基础中间件组。
17年8月-19年3月网联清算有限公司,基础组件组。
一、梦想和被拒
进入阿里一直都是我的梦想,我想这跟很多同学是相似的。我前后被拒了两次,分别是大三找实习和工作一年后。第二次尝试一面都没过,但那一次电话面试经历了一个半小时,被问了十几个问题,面试结束后感觉脑子被掏空了,没办法思考,我也看到了自己的不足,很多基础知识非常不扎实,随机应变能力差。后面针对基础知识做了很多积累。
我看过一篇技术文章,其中一个人写到技术工作者应该偶尔出去面试一下,让外界来评判你的价值,发现自身的不足。我赞同通过跟外部同行对比找出自身不足,但途径可以换成跟社区、优秀的同事交流和学习,毕竟面试是一个耗费体力和时间的事儿。
工作第一年,投出去的简历很少有回应,恰好此时网联正在筹建,同时壹钱包也是网联的股东之一,需要从支付机构借调人力。当时也为面试阿里做了些准备,所以在网联的笔试和面试都很顺利,就这样离开了上海,来到北京。
这里要温馨提示一下各位想进阿里的朋友,要做好充分的准备,不要浪费机会,你的每个回答,都会被记录,虽然你可能因为种种原因失败,但都会为你下一次挑战打下基础。
二、积累
我想强调最好的准备是你认真投入到你当前的工作,把它做的漂亮、优雅,至于一些面试题目和技巧,我个人觉得重要程度没那么高。所以这一章命名为积累而不是准备。
面对挑战的勇气。
16年刚毕业,交给我的第一个任务是学习codis的负载均衡策略,并将其应用到公司自研的分布式缓存上。codis是go写的,我第一反应是我能看懂吗。但还是硬着头皮去看了源码,我印象非常深刻,codis的负载均衡是用三个嵌套的for循环写的,go语言并没有成为障碍,反而给我很多自信。但这仅仅是个开始。
更难的是如何管理集群,扩容、缩容、迁移时集群状态的管理。最初我没掌握方法,一股脑的写,发现实现了A功能,但B功能有问题了,深刻体会到了改了一个bug,引入新bug的痛苦。我把很多功能和判断写在一起,导致这一问题。
探索的过程花了很久,最终我慢慢领悟了一些方法,先将流程肢解开,画流程图,像八爪鱼一样,将每个图中每个块(步骤)用一个函数实现,将所有函数按照流程拼在一起,后面当我发现bug,只在拼接的方法上做了调整,并没有修改太多代码。
经过三个月的开发和测试,完全跑通。这个项目在当年获得了壹钱包年度优秀项目提名,看着其他项目都是百人规模,而这个项目的核心成员只有3、4个人时,自豪感油然而生。这里我也非常感谢我的领导徐超。我的建议是勇于承担任务,逼着自己做些有挑战的工作。
窥源码,知真意。
我非常推荐大家去仔细、认真的去读一个优秀的开源工程的代码。来到网联主要负责消息队列。当时我们选择了RocketMQ,很大程度也是因为相信阿里的技术能力。开始我们并没有着急上线,而是阅读了各个组件的大部分源码,确认了它的同步刷盘、同步复制、消息重试、定时消息等等各种主要功能是如何实现的。
在这期间,一些技术公众号给了我很多帮助。在阅读源码的同时记录源码分析的文档,编写网联内部的《RocketMQ开发者手册》,开讨论会分享源码心得。这是一个漫长的过程,也是比较难受的。因为对于green hand来说,开源代码就像大海,点着点着就不知道去哪儿了,有时一个功能要看一周,而且还会遇到很多不知道的知识点,在主干任务上频繁出现分支,以至于主干任务进行缓慢。
一开始有4个同事一起看源码,最后只剩我一个还在debug。我感受到了解决疑惑的快感,从开源代码中学到了很多技术细节和技巧。窥源码,知真意也是我在即将从网联离职之前给内部培训时的标题。我从中学到了一个优秀中间件的网络线程模型应该是什么样子、内存池技术、如何增强线程功能、如何实现同步流程等等。
在帮助社区写文档时发现一个命令工具返回NaN的问题,提了issue和pr,但并没有被接收,这是第一次尝试贡献源码。后面在跟艾瑞克的交流中,我得知一个参数能提升broker的性能,使用EpollEventLoopGroup,而不是默认的NioEventLoopGroup,但当我修改配置启动时发现启动失败,于是提了一个issue。过了一段时间,很巧合的一次,在我读《Netty实战》时偶然发现boss和worker应该是相同类型,立即动手修改源码,启动,果然没有报错,第二次提pr被接纳了,那一次我知道了LGTM是啥意思。
熟知源码还能帮助我从源码层面定位问题。当时我们开启了CommitLog的预热功能,之前也熟读了预热的实现逻辑,但生产上还是出现了bug,因为对实现逻辑很敏感,在2小时内定位并解决了问题,防止剩余5个IDC出现类似的问题。
我建议如果你在工作中用到Dubbo、ZK或其他组件,甚至不是Java写的,你都可以尝试去搞清楚他们实现的方法,这对于你后面的职业生涯有非常大的帮助,如果你能成为某开源软件的Contributor或者更高,对你求职将会产生巨大的帮助。
读书。
为了搞清楚RocketMQ网络层的实现原理,我尝试去读Netty的源码,并结合《Netty权威指南》和《Netty实战》理解Netty的工作原理和RMQ的使用方法。看过Netty的部分代码给我留下最深刻的印象是好的产品是无数个细节堆砌出来的。去年为了解决RMQ自旋锁和重入锁的使用问题,阅读了《Java并发编程实战》,这是一本非常经典的Java并发的书籍,非常推荐大家深入阅读。
同时我也喜欢读一些我称之为“泛泛而谈”的书,不是说这些书内容平庸,而是内容广度大,能够拓展眼界,推荐大家阅读《大型网站系统与Java中间件实践》。如果你听了我对RocketMQ的描述并感兴趣,推荐你阅读《RocketMQ技术内幕》。阅读不仅是在书本上,极客时间很多专栏和视频课程也非常棒,都是业界大咖精心准备的,这里比较推荐丁奇的《MySQL实战》和丁雪丰的《玩转Spring全家桶》。
训练。
这里特指算法训练。推荐大家使用LeetCode,题目比较经典,分类全面。因为本身是计算机专业,对数据结构和算法有些偏爱。回想一下上学时就被动态规划、二叉树各种虐,说实话我也是在工作这几年才更深入的理解这些数据结构和算法。如果你问这些知识有什么用,我可以给你一些具体的回答。
例如当你熟悉树的结构会帮助你理解数据库索引和epoll的实现,亲身经历,面试官会问为什么数据库索引要用B+树;如果你熟悉字母树会给你提供一种快速前缀搜索的方法;如果你熟悉链表,当有人问题如何实现LRU也可以轻松回答。再回头看HashMap的实现,也会有更深刻的理解,更不容易忘。
我大概AC了300道题目,而且喜欢参加竞赛,有时间就参加,最好成绩是370名。竞赛非常有帮助!!阿里面试其中一轮一定是上机,一个小时做几道题目,跟竞赛的模式非常相似,而且题目大多类似。竞赛能让你形成一种“肌肉记忆”,上机时代码一遍过。很多同学可能会眼高手低,临场出现一些小问题,耽误很多时间。
另一个相似点在于快速思维,题目并不总是常见的,还有一些需要你临场快速给出答案,如果你习惯这种模式,当你遇到这类题目也不会害怕导致大脑空白。由于做过很多题目,以至于我在上机时超额完成任务,当时面试官还“怀疑”我抄袭。这也是一个加分项或者亮点,让你在候选人中更有竞争力。
而且LeetCode还是训练新语言的好帮手,我在学习python时,会用两种语言完成题目,尤其是python的答案有很多写的非常优雅,能快速掌握很多编码技巧,推荐大家尝试一下。
三、结语
如果你想突破自己的天花板,那一定要别人付出更多,这个过程是很辛苦的。如果你做好了充足的准备,那就自信的表达你的观点,不要因为不自信让面试官觉得你掌握的不扎实。如果你不会或拿不准,如实告知即可,遇到不会的很正常,不要不懂装懂。如果你认准了一条路,坚持走下去,你一定会获得很多收获。
·END·
程序员的成长之路
路虽远,行则必至