红帽白皮书新鲜出炉!点击获取,让你的云战略更胜一筹! 了解详情
写点什么

我们为什么要选择小众语言 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:009377

评论

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

Jcenter 停止服务,说一说我们的迁移方案

Antway

android maven Gradle

基于Kubernetes Operator的网易数帆生产级云原生中间件实践

网易数帆

架构 Kubernetes 云原生 operator 中间件

智能小车系列-动力系统(ezPWM)

波叽波叽啵😮一口盐汽水喷死你

pwm ezPWM PWM信号

【XXX高校】软件IT专业学生(恋爱观)调查问卷

洛神灬殇

调查报告 大学生 恋爱

浪潮云再次入围央采2021年云计算服务采购名单

浪潮云

云计算

音视频编解码--编码参数CRF

Fenngton

ffmpeg 视频编解码 视频压缩 码率控制 CRF

微信小程序登录流程详解

frank-say

赋能制造产业智能化转型 百度大脑开放日福州解密

百度大脑

百度大脑 开放日 智能化

生命中的无奈

小天同学

读书 读后感 生命 4月日更

容器 & 服务: 扩容(二)

程序员架构进阶

Kubernetes 28天写作 弹性扩容 4月日更

SCA工具:开源安全威胁一手掌控

华为云开发者联盟

开源 安全 测试 SCA 软件成分分析

资讯|WebRTC M90 更新

网易云信

WebRTC

C盘内存杀手,原来是这款出人意料的被闲置的软件|iTunes

彭宏豪95

效率 工具 4月日更 iTunes

特斯拉行车数据被篡改?专家称车企很难自证清白,保留“数据指纹”的区块链技术在路上

CECBC

指纹

软件 IT 专业的高校学生有关在线课程的问卷调查

程序员历小冰

如何从 0 到 1 开发 PyFlink API 作业

Apache Flink

flink pyflink python 3.5+

如何通过openLooKeng更高效访问HBase?

openLooKeng

Java 大数据 Bigdata MySQL 高可用

最新、最全、最详细的 Git 学习笔记总结(2021最新版)

民工哥

后端 Git Submodule linux运维 代码管理

面向软件 IT 专业的高校大学生课余时间自学情况调查

xiezhr

大学生日常 IT 高校学院 问卷调查

Linux 上 定时备份postgresql 数据库

Yang

数据库 postgresql

被遗弃的 Vector 和 Stack

Kori Lin

Java

排查dubbo接口重复注销问题,我发现了一个巧妙的设计

捉虫大师

dubbo

UT之最后一测

好好学习,天天向上

LeetCode题解:151. 翻转字符串里的单词,栈,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

ArrayList 与 LinkedList 底层结构

Kori Lin

Java

云信技术系列课 | RTC 系统音频弱网对抗技术发展与实践

网易云信

WebRTC 音频

2021高校IT专业大学生就业意向调查问卷

黑马腾云

获取chrome80谷歌浏览器存储的指定网站Cookie数据方法详解

老猿Python

Python chrome 爬虫 Cookie

智能小车系列-串口设置

波叽波叽啵😮一口盐汽水喷死你

串口 树莓派串口 ttyAMA0

百度智能云成中国跳水队独家AI合作伙伴圆梦东京!

百度大脑

百度智能云

IT 专业高校大学生就业方向状况调查问卷

架构精进之路

调查报告 4月日更 InfoQ 写作平台 1 周年

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