写点什么

我们为什么要选择小众语言 Rust 来实现 TiKV?

  • 2017-09-21
  • 本文字数:2753 字

    阅读完需:约 9 分钟

本文是 InfoQ 策划的语言专题其中的 Rust 篇。其他更多内容将在月底结集推出,敬请期待。Rust 是什么?

Rust 是由 Mozilla 研究室主导开发的一门现代系统编程语言,自 2015 年 5 月发布 1.0 之后,一直以每 6 周一个小版本的开发进度稳定向前推进。语言设计上跟 C++ 一样强调零开销抽象和 RAII。拥有极小的运行时和高效的 C 绑定,使其运行效率与 C/C++ 一个级别,非常适合对性能要求较高的系统编程领域。利用强大的类型系统和独特的生命周期管理实现了编译期内存管理,保证内存安全和线程安全的同时使编译后的程序运行速度极快,Rust 还提供函数式编程语言的模式匹配和类型推导,让程序写起来更简洁优雅。宏和基于 trait 的泛型机制让 Rust 的拥有非常强大的抽象能力,在实际工程中尤其是库的编写过程中可以少写很多 boilerplate 代码。

Rust 的生态

Rust 由于有 Cargo 这样一个非常出色的包管理工具,周边的第三方库发展非常迅速,各个领域都有比较成熟的库,比如 HTTP 库有 Hyper,异步 IO 库有 Tokio, mio 等,基本上构建后端应用必须的库 Rust 都已经比较齐备。 总体来说,现阶段 Rust 定位的方向还是高性能服务器端程序开发,另外类型系统和语法层面上的创新也使得其可以作为开发 DSL 的利器。

Rust 的使用情况

Rust 作为一种新锐的语言,具备其独有的优越性,目前在全球落地的项目中比较知名的比如,Dropbox 的后端分布式存储系统(闭源),Firefox 的新的内核 Servo,操作系统 Redox,当让包括 PingCAP 的分布式数据库 TiDB 的存储层 TiKV,TiKV 作为其中的一员,自上线以来非常引人注目,在 GitHub Rust 语言的全球排名项目中,基本上一直徘徊在前几名的状态。

TiKV 是一个事务型分布式 Key-Value 数据库,是作为 TiDB 项目的核心存储组件,也是 Google 著名的分布式数据库 Spanner 的开源实现。对于这样一个大型的分布式存储项目,在 TiKV 的开发语言选择上,我们选择了 Rust 语言从零构建。在今天这个文章里,我想详细聊聊什么驱动我们选择了 Rust。

对于数据库这类基础软件来说,在过去很长的一段时间,我们能选择的编程语言基本只有 C/C++。Java 和 Go 这类编程语言的主要问题还是由于 GC 引起抖动,尤其在读写压力比较大的情况下。另外一方面,对于 Go 来说,一个非常吸引人的特性是轻量级线程 Goroutine,对于开发者来说极大的降低的开发并发程序的复杂度,但是相应的代价是 Goroutine 的 Runtime 会带来额外的上下文切换开销。 对于数据库这样的基础软件,性能显然是很重要的,另一方面,系统需要尽可能的保持 ”确定性”,在性能优化和调试阶段能够更加方便,但是引入 GC 和另一个 Runtime 的问题是会增加这种不确定性,所以在很长的时间内,C/C++ 是唯一的选择。

TiKV 这个项目起始于 2015 年底,当时也是在 Pure Go / Go + Cgo / C++11 / Rust 几个语言之间纠结,虽然我们的核心团队有大量的 Go 语言开发经验,另外 TiDB 的 SQL 层是完全采用 Go 语言开发,Go 带来的开发效率的极大提升也让我们受益良多,但是在存储层的选型上,我们首先排除的就是 Pure Go 的选项,理由也很简单,在底层,我们已经决定接入 RocksDB,RocksDB 本身就是个 C++ 的项目,而 Go 的 LSM-Tree 的实现大多成熟度不太够没有能和 RocksDB 相提并论的项目,如果选 Go 的话,只能选择用 Cgo 来 bridge, 但是当时 Cgo 的问题同样明显,在 2015 年底,在 Go code 里调用 Cgo 的性能损失比较大,并不是在 Goroutine 所在的线程直接 Call cgo 的代码,而且对于数据库来说,调用底层的存储引擎库是很频繁的,如果每次调用 RocksDB 的函数都需要这些额外的开销的话,非常不划算,当然也可以通过一些技巧增大 Cgo 这边的调用的吞吐,比如一段时间内的调用打包成一个 cgo batch call,通过增加单个请求的延迟来增大的整体的吞吐,抹平 cgo 调用本身的开销,但是这样一来,实现就会变得非常复杂,另一方面,GC 的问题仍然没有办法彻底的解决, 在存储层我们希望尽可能高效的利用内存,大量使用 syscall.Mmap 或者对象复用这些有些 hacky 的技巧,会让整体的代码可读性降低,我的判断仍然是得不偿失。

所以后来认真在考虑的只剩下 Rust / C++11,先说 C++11 的问题,其实 C++11 也没啥问题,性能上肯定没问题,RocksDB 是 C++11 写的,在纠结了一小段时间后,我们认真评估了一下我们的团队背景和要做的东西,最后还是没有选择 C++,原因主要是:

  1. 我们核心团队过去都是 C++ 的重度开发者,也基本都有维护过大型 C++ 项目的经历,每个人都有点心里阴影… 悬挂指针、内存泄漏、Data race 在项目越来越大的过程中几乎很难避免,当然你可以说靠老司机带路,严格 Code Review 和编码规范可以将问题发生的概率降低,但是一旦出现问题,Debug 的成本很高,心智负担很重,而且第三方库不满足规范怎么办。
  2. C++ 的编程范式太多,而且差异很大,又有很多奇技淫巧,统一风格同样也需要额外的学习成本,特别是团队的成员在不断的增加,不一定所有人都是 C++ 老司机,特别是大家这么多年了都已经习惯了 GC 的帮助,已经很难回到手动管理内存的时代。
  3. 缺乏包管理,集成构建等现代化的周边工具,虽然这点看上去没那么重要,但是对于一个大型项目这些自动化工具是极其重要的,直接关系到大家的开发效率和项目的迭代的速度。而且 C++ 的第三方库参差不齐,很多轮子得自己造。

Rust 在 2015 年底已经发布了 1.0,Rust 有几点特性非常吸引我们:

  1. 内存安全性
  2. 高性能 (得益于 llvm 的优秀能力,运行时实际上和 C++ 几乎没区别),与 C/C++ 的包的亲缘性
  3. 强大的包管理和构建工具 Cargo
  4. 更现代的语法
  5. 和 C++ 几乎一致的调试调优体验,之前熟悉的工具比如 perf 之类的都可以直接复用
  6. FFI,可以无损失的链接和调用 RocksDB 的 C API

其中放在第一位的是安全性,之前在 C++ 中提到的内存管理和避免 Data race 的问题,我相信虽然靠老司机是可以解决,但是仍然没有在编译器层面上强约束,把问题扼杀在摇篮之中解决的彻底,Rust 这点非常符合我的口味, 对于大型项目来说,永远不要把软件的质量押宝在人身上,人永远会犯错,人是不稳定的。Rust 的做法虽然增加了上手的门槛,但是我认为是值得的。另一方面,Rust 又是一个非常现代化的编程语言,现代的类型系统,模式匹配,功能强大的宏,trait 等在熟悉以后会很大的提升开发效率,其实如果选择 C++ 的话,算上 Debug 的时间,Rust 的开发效率不算低,在我们的实践经验中,我们的工程师从零开始接触 Rust,到能够高效进行开发的时间大概是 1 个月,而且熟练的工程师的 Rust 开发效率几乎是和写 Go 差不多的。

小结

总体来说,Rust 这门新兴的语言对于国内大多数开发者来说会显得比较陌生,但是并不妨碍 Rust 已经在世界范围内作为公认的 C/C++ 的有希望的挑战者。我认为,从长远来看,在对内存安全性和性能有严苛要求的场景,Rust 将会有广阔空间。

2017-09-21 19:009737

评论

发布
暂无评论
发现更多内容

java高级用法之:在JNA中将本地方法映射到JAVA代码中

程序那些事

Java Netty 程序那些事 3月月更

我写的 Python 代码,同事都说好

AlwaysBeta

Python Pythonic

WebAssembly技术_在Web端运行C与C++程序(win10)

DS小龙哥

webassembly 3月月更

使用云服务器ECS搭建DoH服务的开发实践

阿里云弹性计算

征文投稿 玩转ECS DoH

最终信息模式:终结香农极限,语义通信的另类空间

脑极体

阿里云云原生应用平台总经理丁宇:“连接、合作、赋能”,携手加速器伙伴助力企业云上创新

阿里巴巴云原生

5G区块链技术让建水紫陶有了“身份证”

CECBC

数字人民币为全球CBDC监管提供宝贵经验

CECBC

Linux之export命令

入门小站

在线JSON转YAML工具

入门小站

工具

面试官:你在项目中用过 多线程 吗?

田维常

面试 java面试

都是让小程序在app运行,FinClip 与 uniapp有什么区别?

發財KK

小程序 uni-app 前端开发 sdk

电阻电路的等效变换(Ⅰ)

謓泽

3月月更

AI与开源的碰撞 昇思MindSpore TechDay直播来袭

Geek_2d6073

关注:车联网的数据安全问题

發財KK

车联网 物联网 数据安全 隐私安全 信息服务

小程序加入智能家居行业,共创未来美好生活

發財KK

物联网 小程序容器 智慧生活 全屋智能 智能家居生态平台

华为云企业级Redis揭秘第17期:集群搭载多DB,多租隔离更降本

华为云开发者联盟

数据库 redis 集群 GaussDB(for Redis) 多DB

区块链的支付模式

CECBC

去你的35岁危机|ONES 人物

万事ONES

程序员 ONES

聊聊我对敏捷项目交付的理解

老张

交付质量 项目交付

面试官:你在项目中用过 多线程 吗?

田维常

Java 开发 多线程编发编程

女性开发者为您解读数据库的未来机遇与挑战

亚马逊云科技 (Amazon Web Services)

Hero 专栏

超级app+轻应用=未来?

發財KK

移动应用 轻应用 快应用 App生态

创业圈的哈利波特们注意了!霍格沃兹即将开学,谁是你的魔法导师?

创业邦

我们如何建立一套无参考视频质量评价体系?

声网

视频 Dev for Dev VQA

元宇宙跟区块链的关系是什么呢?

CECBC

在线Js,JavaScript压缩格式化工具

入门小站

工具

【Zeekr_Tech】为自动驾驶保驾护航—谈谈主流中间件设计

Zeekr_Tech

自动驾驶 软件架构

cdr2022新版本号V24.0.0301简体语言新增功能

茶色酒

cdr2022

技术平台&应用开发专题月 | 国产化替代的本质是价值替代

用友BIP

用友 用友iuap

前Cisco思科首席工程师、Webex AV1第一人Thomas加入微帧科技!

微帧Visionular

视频编码

我们为什么要选择小众语言Rust来实现TiKV?_语言 & 开发_黄东旭_InfoQ精选文章