不好意思,没达到公司性能目标,决定从 Go 切换到 Rust

开发
Discord 广泛使用 Rust 提升性能和安全性,如我们将它用于游戏 SDK、Go Live 的视频捕获和编码、Elixir NIF、多个后端服务等。

今天分享篇文章关于 Discord 为什么从 Go 切换到 Rust。

如今 Rust 逐渐成为许多领域的一流语言,尽管还是相对较新的语言,但它已经在重塑许多创新行业方面发挥了重要作用了。Rust 凭借其市场领先的性能、内存安全性和并发性功能增强了众多领域。 

下面一起来康康,这篇文章吧!

读取状态服务

Discord 是家专注于产品的公司,先从产品背景聊起,Discord 从 Go 语言迁移到 Rust 语言,以解决 "Read States" 服务的性能问题。该服务负责追踪用户已读的频道和消息,对响应速度有高要求。然而 Go 的内存模型和垃圾收集器导致了性能不稳定,非常影响用户体验。

Go 没有达到我们的性能目标原因

为了解释 Go 不能达到我们理想中性能目标,进行以下 5 个方面解释:

  • 数据结构:使用"读取状态"来存储每个用户在每个频道的读取信息,每个状态包含多个需要原子更新的计数器。
  • 规模:Discord拥有数十亿个读取状态,每个状态服务器有数百万个用户的缓存。
  • 访问模式:每秒有数十万次的缓存更新,以及数万次的数据库写入。
  • 架构:使用Cassandra数据库集群支持缓存,缓存键逐出时数据提交到数据库。
  • 性能问题:每2分钟出现一次延迟和CPU峰值,可能与高频率的缓存更新和数据库写入有关。

那么为什么是2分钟的峰值呢?

Go 语言的垃圾收集器(GC)每2分钟强制执行一次,导致性能短暂下降。我们也尝试调整GC频率但是以无效告终,根本原因是内存分配速度不足以触发更频繁的GC。深入研究后发现,GC 需扫描整个LRU缓存来识别无用内存,是性能峰值的主因。

这样导致了减小 LRU 缓存可以减少GC峰值,但会增加缓存未命中率,从而增加延迟。团队通过负载测试找到了一个折中的缓存设置,但并非完美。最终我们决定将服务切换到 Rust,希望利用 Rust 的优势解决性能问题,提升用户体验。

Rust 内存管理优势

Rust 速度极快,内存效率极高:无需运行时或垃圾收集器,它可以为性能关键型服务提供支持,在嵌入式设备上运行,并轻松与其他语言集成。

Rust 通过独特的内存管理机制避免了与 Go 类似的延迟峰值问题。它采用内存所有权的概念,编译时就强制执行内存规则,自动跟踪并释放不再使用的内存。这意味着在 Rust 版本中,当数据从缓存中逐出时,内存会立即被释放,无需等待垃圾收集器介入,从而减少了性能波动。

异步 Rust

Rust 的异步编程在稳定版中支持不足,社区库虽有支持但使用复杂且错误信息难以理解。尽管如此,Discord 团队决定使用 Rust 的 Nightly 版本,以利用其先进的异步特性。Discord 有采用新技术的历史,愿意面对前沿技术的挑战。他们坚持使用 Nightly 版本直至异步特性在 Rust 稳定版中成熟,最终这一决策证明是成功的。

实施、负载测试和启动

在重写服务为 Rust 版本的过程中,我们首先进行了简单的翻译,然后利用 Rust 的强类型系统和泛型简化了代码。Rust 的内存安全特性也让我们去掉了 Go 中的一些手动内存保护。负载测试显示,Rust 版本在延迟上与 Go 相当,但没有出现峰值。

尽管只是进行了基础优化,Rust 版本的表现已经超越了经过高度手动调整的 Go 版本,显示出 Rust 在编写高效程序方面的优势。进一步的性能优化,如使用 BTreeMap 优化内存使用、替换度量库、减少内存复制,使得 Rust 版本在延迟、CPU 和内存使用上全面超越了 Go。

优化后,我们顺利地将服务推广到生产环境,通过 Canary 节点测试发现了一些边缘情况并进行了修复,之后成功地将其扩展到了整个服务舰队。结果如下:

Go 是紫色,Rust 是蓝色。

提高缓存容量

在 Rust 服务稳定运行几天后,我们决定提高 LRU 缓存的容量。由于 Rust 不受垃圾收集影响,我们能够安全地增加缓存上限至800万个读取状态,提升性能。结果表明,这一变化显著改善了性能,平均响应时间降至微秒级别,而最大响应时间也仅为毫秒级。

不断发展的生态系统

最后,Rust 的另一个优点是它拥有快速发展的生态系统。最近,tokio(我们使用的异步运行时)发布了 0.2 版。我们进行了升级,它为我们带来了免费的 CPU 优势。下面您可以看到,从 16 日左右开始,CPU 一直较低。

总结

从 Go 到 Rust 的初始移植于 2019 年 5 月完成。Discord 广泛使用 Rust 提升性能和安全性,如我们将它用于游戏 SDK、Go Live 的视频捕获和编码、Elixir NIF、多个后端服务等。Rust 的优势包括易于重构的类型安全特性和强大的生态系统。

责任编辑:赵宁宁 来源: 码农渔夫
相关推荐

2024-09-13 09:32:30

2022-06-28 08:03:06

缓存Redis

2020-05-19 13:34:20

ZookeeperZAB协议

2021-07-21 08:48:44

内卷技术竞赛

2015-07-13 09:48:21

iOS

2020-12-17 08:56:51

单例模式JVM

2021-11-18 10:28:27

云计算云计算环境云应用

2019-01-23 10:58:52

接入层架构负载均衡

2020-09-16 09:08:49

订单微服务架构

2013-02-28 09:46:18

程序员岩机Hacker News

2015-12-31 10:23:06

2015公有云中国云市场

2018-07-11 08:19:26

高并发架构网络

2015-09-06 09:50:59

创业大数据

2017-04-26 10:42:27

搜狗输入法

2017-04-26 10:49:25

搜狗输入法

2019-10-18 16:05:32

框架开发Java

2021-04-12 20:42:50

K8S端口内存

2018-12-20 13:53:59

OLEDLCD屏幕

2021-05-17 10:53:49

5G手机4G

2010-09-15 09:28:35

云计算
点赞
收藏

51CTO技术栈公众号