基于Rust语言对Apache Spark性能瓶颈的优化
This-Lynx
闫泽轩 李牧龙 罗浩铭 汤皓宇 徐航宇
目录
-
01 项目概览
-
02 项目背景
-
03 项目设计 & 可行性
01 项目概览
What's our project
项目概览
使用Rust编程语言对Apache Spark性能瓶颈的优化 基于Rust版Spark开源项目vega
02 项目背景
Why we're doing so
从MapReduce开始

举个例子:数豆子(wordcount)
一大堆五颜六色的彩虹豆,若干个人来数一数各种颜色的豆子
-
将彩虹豆堆划分开,每个人来数一堆
-
每个人数到一种颜色的豆子,就在一个小本本上记上一行 | color | 1 | | ----- | --- | | | |
-
小本本上的东西最后汇总起来,这时候就不需要去盯着豆子数了,最后在总表上记好 | color | num | | :----: | :---: | | color1 | num1 | | color2 | num2 | | ... | ... | | colorx | numx |
MapReduce(Apache Hadoop)
之前的模型就是MapReduce,其已足够强大,但是仍然面临一些问题。
- 功能少:只有
map,reduce两种算子 - 容错不优雅:只能从头开始
- 存在依赖的任务容错成本高
RDD(Apache Spark)——MapReduce的继任者
(Resilient Distributed Dataset)

RDD特点
- 只读且被分区的数据集
transformation操作:通过存储系统和其他的 RDDs 进行操作而创建一个新的 RDD,如map,filter以及join等- 不同的算子对应不同的依赖关系,宽依赖与窄依赖

概要设计
两条可行的路线
- 源码基础上对Spark性能瓶颈的Rust重写
- 基于不完善的Rust版Spark开源项目vega的实现
源码基础上对Spark性能瓶颈的Rust重写
从Scala到Rust,从Maven到Cargo
rust与scala对比
- 安全性:Rust编译期进行较为严格的检查
- 高性能:Rust秉承零成本抽象原则,将许多运行时开销(如GC)放置到了编译期,提高了数据处理速度和效率
- 并发性:Rust中同样有函数式编程的理念,这与并发契合
Rust与Scala通过JNI交互

- Scala是在JVM上运行的语言,常用JNI接口与C语言等实现交互。
- 另一方面,Rust可通过二进制接口的方式与其他语言进行交互。
jni crate对JNI提供了安全的Rust接口。
挑战
- 底层实现不同,难以直接相互调用。
- 需要遵守的规范繁杂,限制较多,不易编写代码。
- 网络上交互的尝试较少,缺少合适的参考资料。
- 交互的路径较长,容易带来不必要的性能损失。
基于不完善的Rust版Spark开源项目vega
- vega仓库
- 最近一次更新在2021年
- 不完善,但可用
综合评价
- 源码基础上对Spark性能瓶颈的Rust重写
- Spark文档详细
- 可以保证能运行
- 代码庞杂,无法全部重写
- 只能考虑回调,但极少有人进行尝试,需要自行探索
- 基于不完善的Rust版Spark开源项目vega的实现
- vega文档不够详细
- 已经不再处于被维护状态
- vega总代码量较少,修改起来较方便
- 为原生Rust项目,不需要回调
最终确定基于不完善的Rust版Spark开源项目vega的实现路线
03 项目设计 & 可行性
How we'll get there
理论依据
调度
调度任务类
JobStageShuffleMapStageResultStageTaskShuffleMapTaskResultTaskTaskSetSchedulablePoolTaskSetManager
DAG调度



调度算法
- FIFO方法
- Fair方法:资源使用率低优先
可以改进的内容
- 添加调度算法
- 利用协程的方式进行调度

ShuffleManager
在Spark框架中,Shuffle阶段(类似于MapReduce中的Shuffle)涉及十分密集的磁盘的读写和网络I/O,是极为重要的性能瓶颈。
ShuffleManager
被用于管理块数据 - 提供集群块数据的读写 - 数据的本地读写 - 读取远程RDD结点的块数据 - 通过控制shuffle前后的数据块的读写关系,实现shuffle过程
ShuffleManager可改进的点
其优化至关重要,必须使用当前的SOTA算法。
-
HashShuffleManager(vega已经实现) 为每个Reduce端的Task生成一个文件,从而生成数量惊人的文件,降低I/O吞吐率,并导致Shuffle阶段时内存中积攒大量文件句柄。 -
SortShuffleManager(vega还未实现) 根据分区ID进行排序,然后输出到单个数据文件中,同时生成对应的索引文件。
HDFS
- vega没有接入任何文件系统,作为一个分布式计算系统显然不合理
- Rust开源社区中有提供HDFS支持的包(hdrs)
- 可以将其接入vega,增强对文件的支持
- Spark原生支持HDFS,接入HDFS更容易融入Spark生态
Spark Streaming
- Spark Streaming是Spark的一个扩展模块,使Spark支持流处理。
- 微批次
- 只负责提交任务,不负责计算,改进空间不大
- 作为完成必要内容后的可选项
Spark Streaming内部组件

Streaming Context:Spark Streaming的起始点和上下文
DStream和DStream Graph:封装流式数据和依赖关系
JobScheduler和ReceiverTracker:调度,生成作业,控制Receicer状态
技术依据
编译工具
Maven
- Java项目的构建自动化工具
- 构建软件及其依赖关系
Cargo
- 提供了一系列的工具,为 Rust 项目的管理提供尽可能完整的手段
- 与 Rust 语言及其编译器 rustc 紧密结合
- 能够对该项目的各种依赖项进行方便、统一和灵活的管理
部署测试
Spark build

vega build

vega build

进度管理
| 时间进度 | 进度概览 |
|---|---|
| 第八周 | 系统学习rust |
| 第九周 | 编译,测试vega模块 |
| 第十周 | 定位vega模块 |
| 第十一周~第十四周 | 编写优化对象模块 |
| 第十五周 | 添加拓展模块 |
| 第十六周 | 跑benchmark部署测试 |