从物理转 AI 、战数据库,95后程序员的职业选择

百家 作者:AI100 2022-07-15 22:53:41

【CSDN 编者按】这是一位95后程序员的自我思考之旅,关于为何放弃难得的保研与出国机会、为何离开看似最佳选择的大厂加入前途未知的创业公司、为何从如火如荼的AI领域转入数据库领域的故事。新程序员004》带你走进刘继聪的程序人生希望能给职业成长路上有些许迷茫与困惑的年轻程序员们一点启发。

作者 | 刘继聪

出品 | 《新程序员》编辑部

我叫刘继聪,是复旦大学2015级的学生,最初在自然科学试验班,分流进入物理系,然后转专业进入计算机系,也因转专业政策降了一级,于2020年毕业。我放弃了保研和出国的机会,进入阿里巴巴一年后,加入涛思数据。

刘继聪 TDengine研发工程师,毕业于复旦大学,曾就职于阿里云。目前正在为TDengine 3.0设计并实现全新的分布式消息队列与流式计算引擎。

在我短短三年的职业生涯中,先后辗转字节跳动(实习)、某创业公司(实习)、阿里巴巴、涛思数据。研究方向从NLP(自然语言处理)、ML(机器学习)转为DB(数据库)。本文是我对过去三年职业方向选择的回顾与复盘,希望你读过我曾经历的迷茫与困惑后,不会走上同样的弯路。

本文节选自《新程序员004》 『纸质书+电子刊』已开启订阅


菜鸟起航——从物理系转入计算机系


一个刚刚参加完高考的学生,不会很清楚大学设立的专业是做什么的,进入大学后可能会很难接受所选专业与预期的差距。因此,大二时我选择从物理系转入计算机系。

和计算机结缘,源于物理系的一个项目——实验室设备管理系统。当时,我负责Web与服务器相关的功能,因为无人指导,只能在网上找教程自学。我清晰地记得,当我用“世界上最好的语言”PHP写出第一版程序——一个LAMP架构的CRUD系统时的感受。随着项目的迭代,系统不断重构,前端后续换成了JavaScript,后端则换成了基于Python的Django。

与此同时,我选修了物理系的C++课程,这门课主要讲C++如何应用于计算和模拟方面。我人生中第一个较大的C++项目就是那门课的期末作业:用经典的蒙特卡洛方法,做伊辛模型(Ising model)的模拟。我做了一个命令行程序,只要输入不同的参数,就能够生成对应的模拟结果,并用OpenMP做并行的加速优化。后来我才发现由于数据依赖,我写的并行程序比串行程序慢几倍。

我觉得写代码非常有意思,或许比在物理实验室修设备更有趣,于是,顶着降级的代价,我转入了计算机系。很快我发现,即使我自认为已经写过很多代码,但也一度被各路大神虐得体无完肤。

我所在的拔尖班大部分同学都在ACM队,而数据结构课的老师是复旦大学ACM队教练。整个课程体系非常竞赛化,每周都会用OJ(在线判题系统)测试,OJ类似于LeetCode,但区别在于,它只显示答案错了,却不告知产生错误的输入数据。因此,调试就完全靠猜。开始时,我在测试中一分都拿不到,每周光是完成作业就几乎花掉我所有时间。为了获得更好的测试成绩,有很多次,我都坐在通宵自习室写代码,直到天亮。渐渐地,我能够在每周的OJ测试中拿到满分,期末拿到A。在刚转入计算机系最痛苦的第一学年,我的绩点便拿到全系第一。

后来,我在复旦获得各种各样的奖项:一等、二等、三175等奖学金,以及数模竞赛和物理学术竞赛的国家一等奖和上海市一等奖,还有泛海学者、优秀学生等荣誉(见图1)。从自我怀疑、焦虑不安变得坚定、自信。如今想来,我认为那门数据结构课程是一个台阶,拼尽全力再上一层,才能看到别样风景。也正是这段竭尽全力刷算法题的经历,使我在几乎零准备的情况下进入字节跳动实习,并拿到了各个互联网大厂的秋招Offer。

图1 在复旦大学所获奖项与荣誉

在计算机系的选修课中,我接触到了更广阔的计算机世界与更深入的知识,也做了很多有趣的项目。

比如,数据库课程的期末项目与PostgreSQL有关,要求利用PostgreSQL的框架,实现两个UDF函数,计算字符串的Levenshetein Distance和Jaccard Distance,并且尽可能优化执行效率。通常,优化无非是降低算法复杂度、常数优化。助教提醒我们把PostgreSQL的嵌套循环连接改成块嵌套循环连接,显然这是附加题,且难度较大,很少有同学去做。临近期末季,即使项目完成得再好,也不会比其他人的成绩好多少,而将时间完全投入复习,争取考试拿高分才是更有性价比的选择。不过,在我看来,做项目比复习有意思。在期末考试前的那个周末,我将全部时间投入项目中,看着评测的执行时间从十几秒优化到一秒内,过程中的收获,远比期末的成绩A更重要。

此外,我还选修了分布式系统、数据挖掘、密码学原理,甚至是这辈子都可能不会再用到的信息安全原理、计算理论基础等课程。同时,我和同学组队做了很多有趣的项目,部署Hadoop和Hive、分析不同任务中的性能瓶颈、使用Spark进行分布式计算等等。很多项目,如LZMA压缩算法、Hive的性能分析实验、SVM的实现与收敛分析等,都让我觉得分外有趣。


职业选择——从AI到DB


除了上课,计算机学生的另一条主线是科研与实习。

进入计算机系的拔尖班后,要求选导师、进实验室,由于当时的主流是AI,复旦大学的NLP实验室很强,于是我就加入了NLP实验室。在实验室异常拥挤,本科生一座难求的情况下,稀里糊涂过了一年。当时我想去校外看看工业界都在做什么。

大三时我在字节跳动的AI Lab实习。适逢BERT以横扫六合之势,刷新了NLP众多Task的SOTA(State Of The Art,最高水平),我们基于BERT做中文错别字检测工作,该项目后来发表于ACL会议。

改模型的工作不够有趣,在进入大四前那个暑假,我进入香港科技大学交流,跟着导师研究GAN(Generative Adversarial Networks,生成对抗网络)。虽然我在AI领域学习的导师都是业界、学术界的知名专家,但我却没能产出亮眼的成果,以至于我现在都不敢提他们的名字。

机缘巧合下,一位做数据库的同学引领我接触到另一个领域——Data Infra(数据基础设施)。作为TiDB的贡献者,他也带着我进入TiDB社区做贡献。彼时,我开始系统性地学习分布式系统和数据库,成为开源社区的贡献者,并萌生了去做数据库,更准确地说,去做Data Infra的想法。

临近毕业季,摆在我面前的路有三条:保研升学、参加工作、出国深造。由于保研外校需要参加夏令营(而当时我正在香港科技大学交流),本校又没有特别合适的导师,我便放弃保研,去追秋招的末班车。出国留学是我给自己的后路,因为我有科研经历,能拿到推荐信,英语也不成问题。但出乎我意料的是,秋招非常顺利,我拿到了所有面试公司的Offer,其中既有阿里巴巴、腾讯这类大型企业,也有PingCAP这类创业公司。

在某互联网大厂的终面中,我遇到了一位同样复旦毕业、工作十多年的学长。当我透露出想做数据库的意向时,他反问我:“年轻人都想去做些有技术挑战的事情,我当年也是。但去创业公司做数据库,你真的想好了吗?未来好几年,你可能都比在互联网大厂做业务的同学薪资低,同时还要承担更多不确定的风险,你能接受吗?”

最终,我选择了阿里云,从事基础架构的工作。

秋招结束后,距离毕业和正式入职还有好几个月的时间,我了解到一位学长在某创业公司做技术负责人,便去做了实习生。在那里,我第一次用Go写微服务,第一次接触生产环境中的真正运行的Kubernetes,第一次用C++写TensorFlow……这段经历,也让我对创业公司留下好感,至少不输互联网大厂。

疫情在那个冬天爆发,无法返校,毕业时也只和部分同学匆匆相聚又相别。上海到杭州不过49分钟动车车程,恰如从学生到职场人的转变,快得令人猝不及防。下一站,杭州阿里。


第一份正式工作——阿里巴巴


或许是得益于我之前还算丰富的实习经历,又或许是我在学生时代做了很多有挑战的课程项目,使我很快适应了新的环境,上手了新的工作内容。在入职首月,就解决了一个困扰组内技术专家半年之久的问题。

背景是这样的,当时我们的监控系统探针直接安装在客户的ECS(阿里云服务器)上,客户可能会购买很多ECS,组成集群。我们需要抓取集群内的网络拓扑关系如TCP连接,然后绘制成可视化的拓扑图。该过程相比一般的分布式微服务追踪,难点在于:  

  • 不对客户的技术栈做假设,Java、Python、PHP都有可能;

  • 要做无侵入式,不希望用户改代码; 

  • 要适配Kubernetes、非Kubernetes及各种Linux内核版本。

彼时已经实现的技术方案有根本缺陷,是通过轮询/proc目录下的TCP文件来做的,但问题是,采用轮询方式只能抓取此刻正存在的连接,如果连接是不断发起并立刻释放,那么,轮询方式无法保证抓取全量数据。解决该问题最好的方法是用eBPF,而eBPF是相对新的技术,只有在较新版本的Linux内核中才能得到良好支持。据当时的统计数据,绝大多数客户的技术环境都不能良好支持eBPF。

当我加入后,了解到这个问题已经困扰大家许久,我花了一周业余时间做调研,发现有一个内核模块—auditd,可以较好地解决这个问题。

auditd是一个比较轻量级的内核Log模块,能够在很旧的内核版本中运行,可以对所有的监控系统进行调用,并打出Log。那几天,我的业余时间都在做新方案的Demo。如我所料,它确实可以实现我们要的功能。后来,我又花了几周时间调试,真正将Demo转变成一个生产环境中可用的产品,并将其上线。正因此,我在转正时得到了极好的评价:“确实超出预期了,没想过让他做这件事”。

此外,我每天晚上都会花费大量时间阅读组里的代码,入职第三个月时,我已经可以画出组里系统的架构图,给入职的新人讲解各个模块的划分及其相互关系。入职第六个月,我已经阅读了权限范围内的几乎所有代码。后续随着组织架构的变动,我开始成为一些项目的Owner。

当然,我也遇到过一些不大不小的挑战。比如:对于Java Agent,为了在premain模式下实现字段和方法的添加与删除,我用ByteBuddy写了一套注入工具替换原本的JVM-Sandbox。与此同时,我开始对软件工程和云有了更深的认知,也对基础架构的理解更加深刻——同样被称作基础架构,但工作内容可能天差地别。

如果把云上的众多服务以平台侧和管控侧作划分:平台侧相当于提供云上数据库、消息队列等服务,部署形式对用户可以完全透明,用户可仅以API的方式调用;管控侧的典型特点是侵入性,例如探针,需要将服务安装到用户的环境中。我所在的工作组,工作内容便属于后者,管控侧的麻烦在于适配用户各种各样复杂的环境,其自身的核心能力、技术难度与挑战都明显弱于平台侧。因此,我发现自己进步的速度也渐趋缓慢,组里业务的发展状况也不如人意。

岁末、春节,疫情仍在持续,在那个冬天,我没能回家。

杭州开放了很多免费娱乐,给这个冬日带来了一丝暖意,可我无心玩乐。尽管在这份工作中取得了不错的个人成绩,但我确信一定会离开这里,这一次,我必须确定目标、规划未来。

春节后,我开始和公司内部的不同团队接触,结果却让我失望。很多我以为做着内核研发的部门实际上只做管控和写控制台;还有一些内核部门,工作范围太小;至于其余部门,则并不欢迎校招新人转岗。与此同时,我看到Data Infra的环境正在悄然改变。一些令人振奋的声音传到了我的耳朵里:

  •   “所有人都看好DoorDash这些明星Pre-IPO,而Snowflake这类公司当时招人都挺困难,但那些进去的人后来发现他们的收益远远超过了其他人……” 

  • “Snowflake的发行价已经上调了,上市当天就暴涨了超过100%……” 

  • “Snowflake的数据确实好,它的NRR是173%,也就是说假设一个用户去年在Snowflake上花费了1美元,那么今年他将平均花费1.73美元……” 

  • “Confluent上市、Databricks大额融资……”

这时,我才发现:去创业公司做数据库,已经不再是一件需要靠情怀去支撑的事。随着这个行业内热钱的涌入,有前途的创业公司会获得大额融资,更关键的是,对于这类技术公司,人才是核心的投入与资产,因此,他们愿意花钱,也有充足的资金和大厂抢人。确定大方向后,我又花了一些时间做调研,以找到更具体的目标。

期间,我也在积极地准备面试。一方面,我开始系统性地研究基于LSM Tree的存储引擎,完整阅读LevelDB的代码,阅读部分RocksDB的源码,并对比、分析MergeTree、WiredTiger等存储引擎;另一方面,研究Lock Free与Wait Free等算法,学习Hazard Pointer、RCU等技术,阅读Folly中MPMCQueue的实现。我将学习内容以及过往在数据库领域的经历都写入简历,作为面试的敲门砖。

最终,我敲定首选目标——做时序数据库TDengine的涛思数据。

首先,TDengine是开源产品,我已经多次看到TDengine登上GitHub Trending榜,我能够从代码及其运行直接判断它是否有真材实料;其次,通用OLAP数据库虽然被炒得火热,但竞争也非常激烈,或许不如从细分赛道入手,而在细分赛道中,时序数据库与图数据库的增长最为迅速,我相信IoT设备会持续不断地增长,产出越来越多的数据,我看好它的前景;再次,涛思数据的招聘页上醒目地写着“超越BAT的薪资”,我认同这样的人才观,愿景与待遇缺一不可,如此才能招聘到最优秀的人才;最后,面试本质是双向选择的过程,我需要充分利用面试的机会了解未来TDengine还要做哪些事、有哪些挑战,如果这个产品被认为已趋成熟、只能做些小修小改,那不是我想要的。


新的征程——涛思数据


从杭州搬到北京,我与涛思数据的故事从2021年7月拉开帷幕。数据库内核的研发工作我很快上手,并在转正后的首次季度总结中拿到了“最佳新人奖”(见图2)。

图2 涛思数据“最佳新人奖”

现在,我在涛思数据负责流式计算引擎的研发。TDengine 2.0中提供了连续查询的能力,它本质是一个时间驱动的批处理,无法处理乱序数据的问题,且性能消耗很大。我的目标是为现有的TDengine实现一个真正的流式计算引擎,挑战之大远远超乎此前所有的工作与项目。

我一边系统性地学习流式计算中的Exactly Once Message Processing、分布式快照等容错理论,一边研究Kafka、Flink的源码与实现机制,并跟踪SIGMOD、VLDB、ICDE等大会中相关研究的最新进展,了解Railgun、Hazalcast Jet、Ray Streaming等新引擎的设计,同时关注着Decodable等流式ETL工具和Materialize、KsqlDB这类流式数据库的产品形态与定义。我必须关注前沿工作与数据库领域中的新玩家,因为我不希望做一个在设计之初就落后于时代的产品。

若想TDengine成为流式计算的源,我需要将其改造成一个可重放、可确认的源,类似于Kafka的消息队列,能够高效定位指定的记录、并确认消费记录位点,这比起用Raft Learner异步复制出Change Log的方案要复杂、完善得多。接着,我会改造现有的查询引擎,使其能够在隔离的资源环境中持续运行,并持续接收上游源发送出的数据进行实时增量计算,变成一个流式计算引擎。以一套执行引擎来融合OLAP的查询与流式计算,我会用代码来践行我的想法,也期待焕然一新的流式计算引擎面世。


未完的故事


正如我刚起步的职业生涯,我的故事也才刚刚开始,远未完结,本文或许是一个阶段性的总结。

在我的成长过程中,在我迷茫与挫折时,得到了很多人的帮助。他们有的帮我找到了新方向与道路,有的让我有勇气和决心接受新挑战。因此,我也愿意分享我的经历。不管是在AI领域的曲折,还是在工程领域的相对顺利,以及在我面对选择时的思考与决策,都希望能给你一些启示与帮助。

比起盲目的闷头苦干,我更相信正确的选择对人生和职业有更大的影响。本文复盘了我职业生涯中几个至关重要的选择:从物理系转入计算机系;从研究AI转做Data Infra;从放弃保研与出国到加入阿里巴巴,再到离开阿里巴巴加入涛思数据。

得益于那些充满挑战的课程与项目,为我打下了坚实的技术基础与算法功底,使我有了选择的权利,让我能够快速进入想去的领域。而花费大量时间在多个不同领域中探索,也让我有所得、有所失。我赞同图灵奖得主John Hopcroft的观点:“我不认为本科生做研究是一种好的经历。我不鼓励他们这样做,除非他们想要继续深造,去大学攻读博士学位,那么他们最好发表过论文。但这是不幸的。”

借用强化学习理论,这是一个exploration(探究)与exploitation(利用)的dilemma(两难困境):如果你想利用本科短短几年的时间在某个方向做出好的研究,那么你就要牺牲exploitation,提前开始exploration的过程,而过早的exploration可能陷入局部最优无法逃脱,当某天你意识到这一点,想要调整参数,那时想逃出这样的局部最优又会带来极高的沉没成本。

某种程度上,我庆幸自己没有在物理或AI这些路上走到尽头才想起转身,而是找到了更适合我的方向,让我能做更喜欢的工作。另外,虽然学习、科研与实习是主线,但我也“浪费”了很多时间来享受大学生活中“自由而无用”的快乐。在陷入死胡同时,是很难靠自我力量走出来的,而我有一帮很好的朋友,他们在我迷茫与困惑时让我看到新的方向、给我帮助与力量,这是我大学生活中绝不后悔的一部分。

以上,就是献给和我一样迷茫、困惑的年轻人们的肺腑之言。

— END —

本文节选自《新程序员004》,从MySQL之父、MariaDB创始人 Michael "Monty" Widenius,到PostgreSQL全球开发组联合创始人Bruce Momjian、阿里巴巴副总裁贾扬清、指令集创始人兼 CEO潘爱民、著名科技作者吴军,再到 Vue.js 作者尤雨溪……《新程序员004》以「我们的技术时代,我的程序人生」为主题,与多位国内外知名的技术先锋和新生代程序员代表进行了深度对话,希望行业优秀人物的技术之路与人生感悟给大家带来启发。

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接