黄东旭:最初大概是从1996年,我小学3年级左右,开始接触到QBASIC。当时我放假在家闲来无事,碰巧翻到一本我母亲大学时期的Basic手册,那时家里没电脑,用的是小霸王学习机,而上面的游戏卡带都被我母亲藏起来了,只有一个Basic解释器的卡带,于是我就参照那本书开始学习一些基本的编程技巧。后来我逐渐发现自己在这方面的浓厚兴趣,就开始一步步积累学习,因此差不多到小学毕业的时候,像一些基础的C、Pascal等,我都已经玩得比较熟了。
之后步入初中,我开始尝试像是Windows上用Visual Basic做点小工具的开发。再后来的高中时期,我又将目光投向Linux,此后就一直在使用Linux,包括对整个开源文化的理解,再者就是对GNU和自由以及开源软件运动的那套东西熟悉起来。所以我在编程方面起步比较早,大学阶段就开始参与ACM算法竞赛,毕业以后还做了一段时间桌面应用软件的开发,其后重心又转到后端和分布式系统相关的基础软件上来,并且一直做到现在。
黄东旭:我了解的语言算是比较多的,这里就举一些比较流行的例子。在过去,比如后退大概5到10年,我用得比较多的是Python。因为最早其实从C和C++入门的,当我开始接触Python的时候,就觉得生产力获得了极大的提升,因此当时基本什么东西我都会想用Python去写。而且我还通过Python第一次接触到Functional Programming(函数式编程)的一些思想,所以Python算是第一个我比较喜欢的语言。
后来又慢慢去了解一些分布式和高并发程序的架构,或者说分布式系统开发的时候,对我影响比较大的一个语言是Erlang,而为了学习它我也花费了较长一段时间Erlang其实是我接触的第一个纯函数式语言,但我很喜欢,只可惜一直没有机会在生产环境中使用。我觉得这个语言还是有很多巧妙之处的,包括Mailbox,轻量级进程这种概念。
再后来大约在2013年左右,终于邂逅了Go。因为我本身经常会关注Google 公司的相关信息,所以在2009年Go语言 发布第一个版本的时候,我便有所了解。当时我就发现,Erlang中一些我很喜欢的特性都能在Go里面找到。此外它的语法又特别简单,和C,甚至是Python都非常接近,而写出的程序的性能又远高于Python,因此我迅速地完全转向了Go。当时Go语言社区里国内的人不多,所以我也算是国内玩Go玩得比较早的一波人,而且直到现在我都还是非常喜欢Go,其实这也是由于还没有什么比较大的新东西出现。
此外,我个人不太喜欢Java和Scala,还是比较偏爱C、C++、Python,还有Go。所以去年我们在做分布式存储引擎TiKV的技术选型时,本来也是想用Go的,但后来实践发现在真正面对操作系统底层,或是对性能要求极高的场景下,Go的一些表现其实并不太好,比如说GC的问题,以及Runtime的问题等。众所周知,存储层对性能要求很高,所以无奈之下我们考虑用C++来写,当时是C++ 11。而且鉴于性能的要求似乎也唯有作此选择,但我觉得我个人的C++ 水平并没有高到足以Handle这么复杂的项目,而且我们整个团队成员也没有非常深的C++背景。再者大家也知道C++安全性的一些问题,比如内存泄露的问题,稍有不慎就会比较麻烦,所以当时对此比较头疼。就这样直到2015年7月左右,我们注意到了Rust,此前我们团队里其实没有人写过Rust,因此大家对这个语言都还比较陌生,但是我们在了解之后发现Rust在High Performance和安全性等各方面都恰好符合我们的要求。
黄东旭:Vim,实际上从小到大我一直在用Vim,从来没有用过别的编辑器,当然VB不算,哈哈。
黄东旭:其实这也是没有办法的事情,就比如很多编辑器,像是Atom,还有VS Code都声称支持Vim快捷键,但是真正非常老的Vim用户一定会针对自己的开发环境做大量的定制,包括用了很多的插件,以及很多的自定义脚本,我自己也会写一些Vim的脚本,所以这不是说在其他编辑器里实现了一个快捷键就OK的事情。也就是说一个太过重度的Vim用户很难将其转换到其他编辑器上。而且包括很多现在的编程语言,不管是Rust也好,Go也好,对Vim的支持基本都处在第一优先级,因此准确说不是不想换,而是无法换。
黄东旭:就像我们刚谈到的,我最早接触Rust是在2015年7、8月,我们团队当时也碰巧在做技术选型,所以想看能否在这个社区里找到一个比较好的C和C++的替代品。此外,其实我此前也不时会看到Rust的新闻,只是没有仔细研究过,但在那个时间节点上是真的想要去认真了解Rust这个编程语言。因为Rust一直自称是一种系统编程语言,也就是和C一样的System Program Language,之前也有相关新闻称“Mozilla用Rust来重写浏览器内核”,同时还有用Rust去写操作系统这样的项目,所以我们就考虑是否能在我们的数据库里使用Rust去解决一些问题。然后我们就随即展开了调研,这也是相当于一个自学的过程。
随后我们发现Rust规避了很多C++的缺陷,C++在开发大规模项目的时候存在一些问题和安全隐患,也就是说如果C++水平不够高的话,内存泄露、悬挂指针、空指针异常等状况都会频繁发生,Rust会运用很多PL(Programming Language)领域学术界这些年的创新,尝试解决这些隐患。简言之,就是能用更少的代码,花费更小的代价去写出安全的程序——这是Rust给我带来的最大感受,也是它最大的特点。而且它换得这一切优势的代价是把一定的复杂度转嫁给了开发者,而非运行时。然而,如果使用Java或Go,当然也可以很轻易地写出这种很安全的程序,这完全没有问题,但是其中的代价却变成了运行时GC的开销。当初我们若不想引入这些开销,实际上也没有别的办法,但现在有了Rust,唯一的代价就是你的学习成本会稍微高一些,你可能要稍微转变一下思维方式,这就相当于把一部分复杂度移交给了程序员。而我们团队的程序员都还是比较牛的,对这部分复杂度的控制也还不错,所以截至目前我仍然觉得这个决定非常正确,而且过程中的不适应期也仅有短短一两个月,再到后期的开发效率就基本和Go差不多了,所以其实我还是比较喜欢 Rust 这个语言的,如果一个项目能用C++跟Rust写,那我肯定会选择Rust,实际上它反而比C++更容易上手。
下面简单介绍一下我们这个项目的背景,因为大家知道我们公司做的是一个分布式数据库,我们的Rust是用于整个底层的分布式存储,也就相当于它真正存储数据的地方。
此外还有我们的Raft算法的实现,这一整套全都是用Rust写的,然后这个模块可以视作整个系统非常核心的一个模块,对性能的要求也非常高。这也解释了为什么我们在谈到Performance这个问题时能够那么自信,其中很大一个因素(优势)就是Rust是一个没有GC的语言,它的延迟非常稳定,它的口号是“Zero Cost”,这里的意思是无运行时开销,而这一点恰恰能让性能真正跑得飞快,因此在我看来,无论是数据库,还是操作系统,亦或是浏览器内核,于Rust而言都是一个非常舒服的领域。而且正巧这个语言也处于上升期,当初我们开始看的时候,Rust1.0已经出来一段时间了,我们调研之后觉得没什么问题,于是就从0开始去构建这么一个项目。
其实这一年的过程中,我们也得到了很多来自 Rust Team 的支持,因为毕竟我们应该算是Rust社区里全球唯一一个工业级的开源分布式数据库项目,比如Rust Team官方的周报Rust Weekly中就设有一个名为“TiKV Weekly”的固定栏目,用以通报我们的项目进展。所以我们也给Rust社区回馈了很多东西,包括我们监控的库Prometheus(普罗米修斯),它是一个著名的开源的服务监控系统和时间序列数据库,而我们给它贡献了Rust的客户端,再者我们也帮助Rust Team修改了一些语言层面上的Bug等。几个月前,我们去了一趟旧金山,在那里同Mozilla Rust Team的几位核心的开发者分享了Rust在中国社区的发展,以及我们这个项目未来的Roadmap,同时也算是当面感谢他们提供了一个这么好的语言。他们整体比较Open,也都很有能力,这也更坚定了我对Rust语言的信心,这无疑是一个非常有活力的一个语言,现在唯一需要就是时间。
黄东旭:我觉得目前来说Rust最大的问题就是学习曲线太过陡峭。像一些变量所有权,还有Lifetime等概念,很多开发者起初可能并没有相关意识,所以往往会导致一开始在上手的时候,基本每天都在和编译器打架。虽然这个问题已经列入了Rust Team 2017年的Roadmap,但是因为我本身也并非做编程语言出身,语法规范这一块的走势我也不好评判,所以我目前还没有想到具体的办法解决,不过这个问题的确是存在的。
至于库的问题,我觉得到现在为止库还是欠缺的,比如我们现在需要的Rust的gRPC的一个实现,其实Google在这里还没有给出官方的实现。虽然我们向Rust Team提出了这个需求,他们也安排了社区的朋友在写,但是现在还没有完成。包括futures-rs,就是Rust中实现Future的库 ,对很多语言来说,在异步编程里一个非常重要的组件就是Future,但也是最近几个月才刚刚Release出来,到大规模普及其实还有一段距离。
其实我现在觉得Rust的定位更多还是在后端,属于服务器后端的一个编程语言,但它现在真正针对后端去写应用程序的第三方库还是缺得比较多,所以我们基本上也造了很多东西,包括RPC框架这样的,其实这些在其他语言里基本都已经比较成熟了。但Rust有个优点,就是Cargo,它确实非常好用,我个人觉得要比Go的包管理好一个数量级,所以实际上我并不担心Rust这个社区生态的一些问题,因为它拥有一个良好的Team、一个好的社区、一些好的包管理机制,所以肯定会慢慢沉淀出一些比较优秀的库,包括MIO这样的库其实都已经算是比较成熟了。
另外Rust做得比较好的一个地方就是它和C Library这种Native Code,或者说跟C语言的交互,其代价确实很小,所以很多时候你可以把Rust当作一个高性能的胶水(Glue)语言,比如说你底下要用RocksDB,或者用一些C的Library,但是如果你在上层去调用,不管是用Java、用JNI去调,还是用Go的Cgo这种框架去调,开销都是很大的。但如果直接用C/C++去使用的话,业务开发成本又会比较高,毕竟这些语言其实还比较原始,开发效率没那么高。因此用Rust既可以享受这种新语言带来的开发效率,同时又不会损失掉底层已经写好的C库的性能。而在2017年的Roadmap,就提出了对C++更好的Library支持这一条。之前对C的支持比较好,但对C++则存在些问题,所以做好C++直接Call Native Library的支持也是一个很重要的点。
黄东旭:这个问题可以参见Rust 2017年的Roadmap,其中大约列出了十点,排名第一的是易用性,包括文档以及编程语言方便上手的程度。类似于使用IDE的完整体验则排名第二。其后的第三点是网络库等常用的库都要达到1.0的stable状态,此外还有很多细分。我觉得他们真的很厉害,因为首先他们Core Team的人数并不是太多,但它在语言层面,一者是进来了很多很新的东西,就是吸纳了学术界一些很先进的东西;二者就是在我看来Rust做社区其实要比Go更亲和一些,当然这还是在语言层面的比较。因为GO社区的开放性不是特别的好。关于Go有几个问题,社区一直在提意见,比如错误处理、泛型,甚至是Go的包管理等,但Go Team对此接受起来会更慎重些,这也是Go一贯的风格。不过这可能也是因为Go Team的几个大佬层级都相对较高,像是Go的作者Ken Thompson、Rob Pike,这都是Unix的作者,C 语言大师,还包括Plan 9的作者,阵容过于强大,倒是Rust的背景反而更简单纯粹一些。所以,相较而言Rust Team还是比较Open的,当然很多原则上的问题还是必须要遵守,但在很多情况下还是大家一起出谋划策的状态,这可能就是Rust带给我的感受。
黄东旭:我感觉这个活动真的非常好,而且参与者也很积极,此外Topic的质量也相当高。于我而言,这种工作坊性质的活动可能会比大会形式要更好一些,因为在这里真的能够有一段很长的时间沉浸式地去讲这些东西,所以我觉得这个形式还是很有意思的。