上周末在知乎看到一个问题“都说现在编程技术更新速度快很多技术会过时,那么有哪些技术不容易过时呢?”,临时起意做了一个回答,没想到点赞数很快破千,成了热门回答,感觉很多技术人都比较关心这个问题。趁着在北京大兴酒店隔离有闲,把这篇回答扩展成一篇文章,结合我研发 TDengine 的经验,再更加深入地展开阐述一下,分享给研发同学。
把握最基本的原理和方法,你永远不会被淘汰
我是 1984 年高中一年级时开始写程序的,见证了整个 IT 的高速发展。表面上技术发展很快,特别是与用户直接接触的前端技术包括人机交互部分,但计算机的基本技术和原理都没有什么变化。
如果要我重新学一次计算机专业,我一定会认真上几门课,1:数据结构,2:算法,3:计算机体系结构,4:操作系统,5:编译原理,6:计算机网络,7:数据库,8:软件工程。再从自己的兴趣出发,学习一下数字信号处理、数据分析相关的课程。这些课里学到的知识,至少我 30 年前在用,现在仍然在用。我可以肯定的说,这些课里的知识掌握的很熟悉的,技术水平一定高。
以我自己创业开发的时序数据库(Time-Series Database)TDengine (http://www.tdengine.com)为例,我们开发了自己的内存管理、文件管理、调度器、消息队列,使用了多种索引方法、排序等等。如果你不能随手写一个二叉树、Hash,你都没法做 TDengine 的研发工作。虽然这些基本的原理都有现成的库,但针对自己的场景,比如时序数据场景,很多情况下都不能直接用,或性能不够,因此就一定得自己写,而自己写的话,不掌握那些原理是写不出来的。
举一个例子,操作系统课程里介绍的“生产者-消费者”问题,就是一个经典问题,在很多场景下,你往往都会遇到,比如 TDengine 里的查询调度就需要。只有你对生产者消费者问题完全搞清楚,你才可能把异步线程通讯搞明白,随手拈来。在 TDengine 的程序里,我们就使用信号量来将网络的异步操作转化为用户侧的同步操作。再举个例子,比如编译原理,工作中不太可能有任务要你写一个编译器,但是学会了编译原理,你对怎么最大程度地去优化自己的程序、学一门新的编程语言、写个简单的 parser ,就会得心用手。
我个人最推崇的是认真学习操作系统这门课,因为它讲的都是各种资源的管理和调度,包括 CPU、内存、网络、外围设备等等。世界上绝大部分 IT 系统都是管理这种或那种资源,抽象地来看,与 CPU、内存、外围设备的管理其实没任何区别。因此你可以用操作系统课里学会的方法、算法去解决其他实际问题。
所有这些计算机的基本原理、方法几十年都没变,我们只是把它组合起来,去解决新的问题,比如区块链,再比如 IoT 场景下的时序数据处理。因此只要把握最基本的原理和方法,你就永远不会被淘汰。
掌握了基础的原理和方法,还要学会做创新
以底层基础软件的实现来说,很多基本的原理和方法都没有变过,但是为什么做出来的产品,所呈现出的性能、市场竞争力却有很大差距?原因还是在于如何巧妙运用这些原理和方法,就像数学、物理公式一样,复杂难题的解析也是看你对这些公式的理解和运用程度。
以实现一个时序数据库(Time-Series Database)为例,为实现水平扩展所采取的的分片分区策略,其实都是操作系统、数据库里的基本内容,使用的客户端服务器之间的通讯也都是计算机网络中最基本的传输协议,构建索引所使用的也都是基础的索引方法,等等。一个好的产品功能,脱胎于用户和市场需求,建立在众多基础原理和方法的创新之上。
在时序场景下,IoT 设备规模可能达到千万甚至上亿,每秒产生的数据就能高达千万、亿级别,面对这样大的吞吐量,普通数据库根本难以承受,那我们在开发时序数据库时,就要考虑数据如何充分利用时序数据特点来做分区分片、如何更好地实时构建索引等等,这些极具挑战性的实际问题的解决思路就是要创新。
以 TDengine 为例,为了更好地解决这些问题,TDengine 从最初就自研了存储引擎,创新地提出了“一个数据采集点一张表”与“超级表”的概念。我们从传统的数据库里吸取了 WAL,Skip List 等方法,同时把流行的 LSM Tree 做了很大的改动,把树层级结构去掉了,变成了只是按时间段分区、按时间线分块的数据块。这种对存储引擎的创新设计,也让 TDengine 与典型的 NoSQL 存储模型相比,实现了标签数据与时序数据完全分离进行存储,不仅极大地降低了因为标签重复存储所带来的存储空间的浪费,还能够极为高效地实现多表之间的聚合查询,使得千万级别规模的标签数据查询可以在毫秒级别返回。
在我 2008 年创业做和信时,就是一台手机一个消息队列,现在物联网数据的处理,和我当年做消息队列模块相比,在存储架构上,只是一个结构化与非结构化的区别,前者是为了更高效地做各种计算和查询,但在实际应用中,我们还需要考虑到多个设备间数据如何进行高效聚合,我很快就想到了对策,那就可以用数据分析中的维度表、事实表的模型来解决,这样一来,超级表的概念也就出来了。
TDengine 受这些经典数据结构的启发,使用到的也都是流行十几年甚至更久的基础技术,但在此之上还有对技术的合理运用和不断创新,最后才真正成为一个为时序数据场景量身定做的数据库产品。
对于开发者来说,掌握基础的技术知识和原理是迈进这个职业门槛的一个通行证,如果是一个有追求的人,真的想要在工作中有所建树,还想往上更进一步,那就还应该时刻思考怎么运用好这些知识,怎样才能更快速去获得一些对代码的创意思考。
想要往上走,就一定不能躺平
软件特别是基础软件开源,已经成为不可抵挡的潮流,对于开发者来说,这是最好的时代,你不需要苦思冥想自己瞎琢磨,很多时候也不用完全从 0 到 1 去进行一个设计思考。开源项目就像是一本书籍,你总能从中获得一些超出你认知的对于基础技术的创新运用,毫无疑问,站在前人的肩膀上,你能看到的会更远。
就拿编程语言来说,因为互联网行业本身变化大,发展迅速,编程语言也是五花八门,除了 Java、JavaScript 一类的,近几年新出的还有如 Go、Rust、Dart、Kotlin、Swift 等等,在应用型技术占比很高的行业中,对于语言的掌握也要相对广泛一些,好在这些流行语言还并不是很难掌握。
还有些偏底层的语言,本身是很强大的,开发需求低,所以一直都很稳定,C 语言就是这类语言的代表,学好了几十年后也不会过时。但难点就在于这种语言比较难掌握,而且大多涉及硬件和操作系统底层,所以很多人都会对 C 语言望而却步。但事实上 C 语言非常值得学习,它的灵活性极强,向上可以写应用,向下可以写硬件,如果哪一天互联网衰败了,依靠对这门语言的精通完全可以让你平移到其他赛道。
TDengine 就是一款使用 C 语言自主研发的时序数据库(Time-Series Database),没有使用任何第三方的库,一切都是自己开发,包括定时器、RPC 等模块等,并且已经开源。当初我选择 C 语言作为开发语言的原因,其实是受到了 SQLite 的影响,它没有服务器,仅仅一个 C 语言库,整个数据库存放于单一跨平台的文件,支持 ACID,零配置,而且体量可以仅为 600KB。我很庆幸TDengine 选择了 C 语言,虽然确实有一系列头疼问题,如内存泄露、无效指针、多线程同步等,但这些都在后期优化中得到了改善,而 TDengine 所拥有的无依赖、体量小、内存远远小于 InfluxDB、OpenTSDB 等其他时序数据库这些优势,都是非常显著的。
参与开源项目也是学习编程语言的一个好方法,要知道,流行的开源项目都是经过实践推敲、比较成熟的代码创作,认真去研读相关项目的源码,然后再依靠学习到的代码思路去解决问题,这会让你在语言学习上事半功倍。如果你正在迷惑,不妨参与到 TDengine 开源项目中来,只要你真心有投入,我乐意花时间与你一起探讨问题。
结 语
以前很多人质疑过我,认为我不是一个从 Oracle、DB2 核心团队出来的人,怎么能研发Database?但如果你深挖了我的背景,知道我从 1997 年起就在做分布式高可靠的无线核心网络设备研发,也明白消息队列与时序数据之间的相似之处后,你就不会奇怪了。就像我开篇时说的,技术圈里很多的基础原理和方法,几十年都未曾改变,善于思考总结的人总会从中得到相关的规律。可能正是由于我是跨界过来的,比起沉浸在数据库领域多年且已经形成技术思想固化的开发者,才更容易在基础原理和方法的运用上,想到创新甚至是颠覆式的设计思路。
所以,过时的不是基础的技术原理和方法,而是人的思考能力以及没有跟上节奏的对技术的认知。
陶建辉
2022年5月29日于北京大兴隔离酒店