
本文最初发布于 THENEWSTACK 博客。
ClickHouse 是一个开源的分析型数据库系统,包含 150 万行代码,其中大部分是用 C++ 编写的。众所周知,这是一种不安全的语言,因为用它编写的代码可能会有难以发现的漏洞被恶意攻击者利用。
经常有文章提到,Rust 编程语言 可以凭借其在内存和线程安全方面的优秀处理能力取代 C/C++。还有很多大型代码库,如 Linux 内核(C)和 Windows(C++),都是用几十年前的语言变体编写的,所以很多人都在考虑同样的问题。
ClickHouse 的维护者已经踏上了这条道路,目标是对 ClickHouse 中用 C++ 编写的功能进行转换,甚至可能重写整个代码库。
在 ScylaDBvirtual P99 大会 上发表 主题演讲 时,Clickhouse 首席技术官兼联合创始人 Alexey Milovidov 提出了一个关键的问题:“如果今天重新开始,我们会用 Rust 语言编写 Clickhouse 吗?”
Milovidov 解释说,最终,核心开发人员选择了一条渐进式迁移路线。他们首先将 Rust 集成到构建系统中,然后为各种功能构建模块。
在这个过程中,他们遇到了无数的挑战,包括确保构建过程的可重现性以及管理依赖关系。
Milovidov 指出,“Rust 可能很完美,但当你将 C++ 和 Rust 一起使用时,可能会有问题”。
C++ 的代价是需要一个巨大的构建系统
正如 Milovidov 所指出的那样,用 C++ 编写关键任务应用程序仍然有很多优势。他说,“它技术成熟,广受认可,应用广泛。招聘具备 C++ 技能的人才很容易,而且大学仍在教授 C 语言。”
他补充说,“但使用 C++ 需要付出很多努力”。你会遇到内存损坏、段错误或竞态条件等安全问题,而且几乎不可避免。
事实上,ClickHouse 最终构建了一个“巨大的”基于 CMake 的持续集成系统,只是为了确保所有这些类型的漏洞都能被捕捉和修复。
其代码库平均每天有 70 个拉取请求和 145 次提交,持续集成系统会进行“数十亿次测试”——实际上是通过不同的组合执行“数千万次”的独立测试,所有这些都旨在确保新代码不会引入任何新的漏洞。
C++ 令人头疼吗?Milovidov 为此专门准备了一整张幻灯片……
Rust 之旅
核心开发团队觉得,“也许是时候用 Rust 重写了”。这种语言提供了内存和线程安全。它提供的库也更多,特别是在新兴的数据标准方面,如 Apache Iceberg。而且,这种语言似乎正吸引着所有年轻、有抱负的软件工程师。
然而,完全用 Rust 重写 ClickHouse 将需要数年时间。
取而代之,团队决定采取一种迭代方法,将 ClickHouse 系统的各个部分用 Rust 重做,然后用 Corrosion 与 CMake 集成。
首先,他们向 SQL 添加了一个用于 BLAKE3 哈希 的函数,用 Rust 编写并 封装为 C++ 接口。随后,在外部贡献者的协助下,他们增强了命令行界面 clickhouse-client,优化了历史记录管理和导航体验。此外,他们还接受了一项 SQL 替代方案的拉取请求。该方案是一个名为 PRQL(流水线关系查询语言)的库,也是用 Rust 语言开发的。
随着对 Rust 的信心越来越强,项目也变得越来越大。接下来的 Rust 测试是集成一个基于 Rust 的 Delta Lake 格式 库 Delta-kernel-rs。这是一个 Rust 库领先于 C++ 库的典型案例,即便 C++ 未来能实现类似的功能,也远不及 Rust 的实现速度。
Milovidov 说,ClickHouse 本可以自己用 C++ 编写一个 Delta Lake 库,但这项工作将“毫无意义”。可怜有些程序员要耗费大量的时间编写解析 JSON 文件和重定向 HTTP 请求的代码。直接使用 Databricks 官方发布的 Rust 版本显然要轻松很多。
Rust 和 C++ 的危险之处
通过这些实验,ClickHouse 开发人员了解到了 Rust 语言的一些不足之处,特别是当与 C++ 一起使用时。
其中一项挑战是可重现构建,这是确保代码安全、避免意外从互联网下载的关键。此前,Clickhouse 已在 C++ 环境中实现了可重现构建,但转向 Rust 语言后,他们不得不重新思考如何确保构建过程的完全隔离。
为 Rust 程序编写 C++ 封装器也是一个挑战。判断应在 C++ 还是 Rust 中分配内存往往令人头疼。在这个过程中,模糊测试工具 和 Clickhouse 的 CI 系统为错误排查工作提供了极大的帮助。
每种语言在压力下的表现也有所不同。
Miloovidov 认为,与 C++ 相比,Rust 程序和库发生恐慌(panic)的频率过高。这些恐慌可能源于程序错误(表明该库需要更完善的测试),也可能是代码作者将 异常终止 替换为恐慌终止(此做法往往不被 Rust 社区所认可)。
对于批处理作业来说,恐慌是可以接受的,但对于实时运行的服务器和交互式应用程序来说,就不太受欢迎了。
Miloovidov 说,“Rust 库往往会过度使用 panic,即使在不恰当的情况下也是如此,我们不得不一一排查并修复这些情况,以免我们的服务器应用程序突然终止”。
Miloovidov 断言,Rust 代码不应该如此频繁地引发 panic。
就像 Clickhouse 团队在 C++ 库中发现了需要修复的 Bug 一样,他们在 Rust 库中也发现了大量的 Bug。
Miloovidov 还深入探讨了将 C++ 和 Rust 在同一环境中混合使用时出现的许多特殊问题,包括使用 sanitizer、管理交叉依赖、交叉编译以及代码可组合性等具体问题。其中许多问题都源于所需构建系统的复杂性。
转向 Rust 还有一个意想不到的副作用:依赖增加。就整个代码库来说,Clickhouse 只有 156 个依赖项。当引入 Rust 模块时,他们发现自己需要额外管理 672 个传递性依赖(Miloovidov 调侃说,仍然不像使用 NPM 时那么多)。
Clickhouse 的结论
目前,Clickhouse 决定不用 Rust 重写整个数据库系统。但他们对这门语言有足够的信心,并欢迎第三方贡献者提交他们自己的 Rust 语言 Clickhouse 插件。
Miloovidov 说,“Rust 是一门伟大的语言”。
原文链接:
https://thenewstack.io/moving-from-c-to-rust-clickhouse-has-some-advice
声明:本文为 InfoQ 翻译,未经许可禁止转载。
今日好文推荐
Yann LeCun终于被小扎“逼得”离职创业了!内行被外行指导、时刻担心被裁,Meta 人现在迷茫又内卷
一次性应用出现,个人独角兽崛起:顶级布道师Jeff Barr论AI如何重塑开发者生态|InfoQ独家采访Jeff Barr
印度迎来AI工具“0元购”时代!OpenAI、谷歌等巨头内心os:别急,先让他们上瘾,我们再来收费
黄仁勋、李飞飞、Yann LeCun等六位AI顶级大佬最新对话:AI到底有没有泡沫?








评论