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

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

作者 | 刘继聪

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

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

刘继聪

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

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

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

和计算机结缘,源于物理系的一个项目——实验室设备管理系统。当时,我负责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的实现与收敛分析等,都让我觉得分外有趣。

2、职业选择——从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分钟动车车程,恰如从学生到职场人的转变,快得令人猝不及防。下一站,杭州阿里。

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

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

背景是这样的,当时我们的监控系统探针直接安装在客户的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还要做哪些事、有哪些挑战,如果这个产品被认为已趋成熟、只能做些小修小改,那不是我想要的。

4、新的征程——涛思数据

从杭州搬到北京,我与涛思数据的故事从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的查询与流式计算,我会用代码来践行我的想法,也期待焕然一新的流式计算引擎面世。

5、未完的故事

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

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

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

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

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

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

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


作者介绍:

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

新程序员001-004》全面上市,对话世界级大师,报道中国IT行业创新创造! 

猜你喜欢

转载自blog.csdn.net/programmer_editor/article/details/124442396
今日推荐