Spark 3.2.0 版本新特性 push-based shuffle 论文详解(二)背景和动机

前言

本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见大数据技术体系


目录

  1. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(一)概要和介绍
  2. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(二)背景和动机
  3. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(三)系统设计
  4. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(四)实现优化
  5. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(五)评估结果
  6. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(六)相关工作
  7. Spark 3.2.0 版本新特性 push-based shuffle 论文详解(七)结论

思维导图

在这里插入图片描述


2、 背景和动机

在本节中的,我们提供 Magnet的背景和动机。

第 2.1 节回顾当前的 Spark Shuffle 操作。

第 2.2-2.4 节讨论了我们在大规模运营 Spark 基础设施时遇到的主要的 Shffle 问题。


2.1 当前的 Spark Shuffle 操作

如前所述,Stages 之间的中间数据通过 Shuffle 操作传输。

在 Spark 中,Shuffle 执行的方式基于部署模式略有不同。

在 LinkedIn,我们在 YARN 上部署 Spark,并利用外部 Shuffle 服务来管理 Shuffle 数据。

关于 YARN 请参考我的博客——谈谈你对YARN这个框架的理解?

这种部署模式也广泛采用整个行业,包括一些拥有着最大规模的 Spark 集群部署的公司,例如 Netflix ,Uber 和 Facebook。

利用这种 Spark 部署,Spark 工作中的 Shuffle 操作如图 2 所示:

在这里插入图片描述

图 2:Spark Shuffle 操作中 3 个主要步骤的插图

  1. 每个 Spark Executor 在启动后都会和位于同一个节点上面的 Spark External Shuffle Service (ESS)进行注册。此类注册允许 Spark ESS 了解来自每个注册 Executor 的本地 Map 任务产生的物化 Shuffle 数据的位置。请注意,Spark ESS 的实例在 Spark Executor 的外部,并且可以在多个 Spark 应用程序中共享
  2. Shuffle Map Stage 中的每个任务都会处理部分数据。在 Map 任务结束时,它会产生 2 个文件,一个用来存储 Shuffle 数据,另一个用来索引前者的 Shuffle 块。为了这样做, Map 任务会根据分区键的散列值对所有转换的记录进行排序。在此过程中,如果无法在内存中对整个数据进行排序,则 Map 任务会溢出中间数据到磁盘。一旦排序,将生成 Shuffle 数据文件,其中属于相同 Shuffle 分区的所有记录都会被组合到一起,放到一个 Shuffle 块中。还会生成匹配的 Shuffle 索引文件,用来记录块边界的偏移量。
  3. 当下一个 Stage 的 Reduce 任务开始运行时,它们会查询 Spark 的Driver 以获取输入的 Shuffle 块的位置。一旦此信息变为可用,每个Reduce 任务将会建立和对应的 Spark ESS 实例的连接,以便获取其输入数据。 Spark ESS 在接收到这样的请求时,会利用 Shuffle 索引文件来跳到 Shuffle 数据文件中对应块数据,从磁盘读取它,并将其发送回 Reduce 任务。

通过基于排序的方式将 Shuffle 数据物化到磁盘,Spark Shuffle 操作在性能和容错之间实现了合理的平衡

此外,通过从 Spark Executor 解耦,Spark ESS 为 Spark Shuffle 操作带来了额外的好处:

  1. 即使 Spark Executor 正在经历 GC 停顿,Spark ESS 也可以为 Shuffle 块提供服务。
  2. 即使产生它们的 Spark Executor 挂了,Shuffle 块也能提供服务。
  3. 可以释放闲置的 Spark Executor 来节省集群的计算资源。

然而,当我们运营 LinkedIn 公司这样规模的 Spark 基础设施,仍然会遇到 Shuffle 的多个问题,这已经成为了系统可靠性,高性能和可扩展性的潜在瓶颈。

我们将在下面一节中讨论这些问题。

2.2 低效的 Shuffle 期间磁盘 I/O

在 Spark Shuffle 操作中观察到的最大问题之一是由于小 Shuffle 块导致磁盘 I/O 低效。

由于 Spark ESS 每个 FETCH 请求只会读取一个 Shuffle 块,因此Shuffle 块的平均大小决定了每次盘读的平均数据量。

在 LinkedIn,我们在 Spark 集群中主要使用机械硬盘(HDD)来存储 Shuffle 中间数据。

这是由于大规模存储需求下机械硬盘(HDD)比固态硬盘(SSD)成本更低,而且固态硬盘存储临时数据的时候(如Shuffle Data)磨损会更严重。

对于机械硬盘,服务于大量的微小随机读会受到 IOPS(每秒 I/O 操作)的限制。

此外,Shuffle 数据通常只会读取一次,而且单独的 Shuffle 块会以随机的顺序访问。

这样的数据访问模式就意味着缓存不能帮助提高磁盘的 I/O效率。

机械硬盘的 IOPS 和 Shuffle 数据的访问模式的组合导致磁盘吞吐量低,并且抓取 Shuffle 块的时候也会带来进一步的延迟。

在 LinkedIn 生产环境的 Spark 集群中,尽管平均每天 Shuffle 数据的尺寸很大,2019 年年底达到几 PB,但是平均每天的 Shuffle 块计数也非常高(数百亿次)。

平均 Shuffle 块的大小仅为十多 KB,这会导致获取到 Shuffle 数据延迟很大。

图 3 绘制了平均的 Shuffle 块尺寸与每个任务平均 Shuffle Fetch 延迟的相关性,其中产生重大延迟的 Shuffle Reduce Stage 有 5000 个(这里的重大延迟指的是每个任务大于 30 秒)。

在这里插入图片描述

图3:采样 5000 个产生重大延迟的 Shuffle Reduce Stage 散点图。 该图展示了每个任务平均的 Shuffle 延迟和平均的 Shuffle 块大小。 散点图右侧的条形图显示了该数据集中的 Shuffle 块大小的分布。 大多数数据点尺寸都很小。

这些 Stage 是取样自 2019 年 4 月的生产集群中运行的 Spark 作业。

该图还展示了这 5000 个 Stage 块尺寸的分布。

从这个图表来看,我们可以观察到大多数产生重大延迟的都是那些块尺寸很小的
Shuffle Reduce Stage。

虽然 Shuffle 块尺寸过小看起来通过正确的配置 Map 和/或 Reduce 任务的数量来解决,但是我们认为这并不易实现。

我们的集群中确实存在错误配置的 Spark 应用,相对于要被 Shuffle 的数据来说, Reducer 的数量设置得太大。

在这种情况下,参数自动配置的解决方案可以帮助解决这个问题。

要么可以减少 Reducer 的数量,要么可以增加切分的大小来减少 Mapper 的数量。

然而,协调困境依然存在,我们通过改变参数来提高 Shuffle 的性能可能会对作业的其他方面产生负面影响。

这主要是由于参数变化导致每个 Map / Reduce 任务的数据处理量增加了。

此外,这种协调困境会导致小 Shuffle 块不断增加

对于有 M 个 Mapper 和 R 个 Reducer 的 Shuffle,如果每个任务处理的数据量一样,则 Shuffle 块的数量(M * R)会随着 Shuffle 数据量 D 的增加呈现指数级增长。

这会导致随着 D 的增加 Shuffle 块的大小呈现 (D / M * R)的减少。

基于我们在 LinkedIn 为数千名 Spark 用户提供支持的经验,当工作负载增加时需要保持每项任务处理的数据量相对恒定,这是经过实践验证的。

水平伸缩 Spark 应用(更多的 Executor)而不是垂直伸缩(更大的 Executor ),可以避免在多租户集群中难以获取到 Executor 容器。

它还可以防止由于资源的过度配置导致资源利用率降低。

在 LinkedIn,由于加入平台的成员数量越来越多以及建立更复杂的 AI 模型的需要,数据分析和机器学习的工作负载会比以前处理更多的数据。

基于上面的分析,这种处理更多数据的需求会导致 Shuffle 块大小不可避免的减小。

2.3 Shuffle 全量连接的可靠性

我们所观察到的另一个常见问题是,在 Shuffle 期间和 Spark ESS 建立 RPC 连接的可靠性。

如前所述,在 Shuffle Reduce 阶段,每个任务都需要与所有的 Shuffle 服务建立连接来获取它的输入。

对于一个有着 M 个 Mapper 和 R 个 Reducer 的 Shuffle 来讲,理论上,总共需要建立 M * R 个连接。

在实践中,相同 Executor 上的 Reducer 每个目的地会共享一个对外连接,并且使用相同的 Spark ESS 进行注册的 Mapper 每个数据源会共享一个对内连接。

因此,对于一个使用 S 个 Spark Shuffle 服务和 E 个 Executor 的Spark 应用程序,仍然需要 S * E 个连接。

在大规模部署 Spark 系统中,S 和 E 都可以高达 1000。

对于大规模的 Spark 集群,可能会发生间歇性的节点可用性问题。

此外,由于 Spark ESS 是一个共享的服务,当 Spark ESS 受到一个贫瘠配置的作业影响或者在高峰时段 Shuffle 的工作负载还在不断增加,它也可能受到重压而降低可用性。

当 Reduce 任务在建立与远程 Spark ESS 的连接时出现失败的情况,它会立即失败整个的 Shuffle Reduce Stage,导致前面的 Stage 重试,来重新生成拉取不到的 Shuffle 数据。

这样的重试会很昂贵,会导致 Spark 应用程序运行时的延迟过高,这就破坏了生产流程的 SLA。

SLA 请参考我的博客——SLA是什么?

2.4 Reduce 任务的数据放置

尽管有些研究声明数据的本地性在数据中心计算中不再重要,但是其他的研究却显示数据本地性仍然有很多好处。

虽然过去十年的网络速度显著增加了,但正如 2.2 节中讨论的,由于主轴磁盘的 IOPS 的限制,我们常常无法使网络带宽饱和。

我们在第 5.2 节中会运行基准测试进行验证。

此外,如果 Shuffle 块在 Reduce 任务中本地可用,则任务可以直接从磁盘读取,绕过 Shuffle 服务。

这也有助于减少 Shuffle 期间的 RPC 连接数。

尽管 Shuffle 数据本地性可以提供这样的好处,但是 Spark 当前的 Shuffle 机制会导致 Reduce 任务的数据本地性很少,因为它们的任务输入数据分散在所有的 Map 任务中。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值