Spark Tuning 帮助您优化资源(上)

正如我们 2022 年的调查显示,Apache Spark 有望继续成为大数据最主要的大规模大数据处理平台。因此,如果 Spark 用户想充分利用他们的 Spark 环境,他们就必须学习和掌握 Spark 调优。

但是在 Spark 中调优是什么?它是如何完成的?继续阅读以了解有关 Spark 调优的更多信息。

Spark 性能调优是调整 Spark 环境配置的过程,以确保所有进程和资源都得到优化并顺利运行。为确保最佳性能并避免代价高昂的资源瓶颈,Spark 调优涉及对内存分配、核心利用率和实例配置的仔细校准。此过程可最大限度地提高系统的效率和有效性,以确保每次都能获得最佳结果。

我们已经看到许多大数据工作负载在 Spark 上运行,可以肯定的是,在可预见的未来,更多的应用程序和进程将迁移到 Spark 框架。

大多数企业都在运行 Spark,主要是在 Kubernetes 框架上。使用 Kubernetes 运行 Spark 为 Spark 应用程序提供了一个优势——支持按需自动部署,而不是利用持续运行设置的资源密集型模型。这也使您的应用程序能够轻松跨服务提供商并简化管理流程。使用 Spark-Kubernetes 配置可以提高 Spark 资源的利用率,同时降低云成本。

即使将 Spark 与 Kubernetes 一起运行具有广为人知的优势,包括更好的性能和更低的成本,但如果一切都未优化,尤其是 Spark,它可能会很快失败。我们想花一些时间更深入地探讨一个主题:通过 Spark 调优进行 Spark 优化的 Spark 优化。

Spark 开发人员在处理大量数据时需要担心很多事情:如何有效地获取数据源、执行 ETL(提取、转换、加载)操作以及大规模验证数据集。但是,当他们确保程序没有错误并在所有必要的环境中得到维护时,他们往往会忽略一些任务,例如调整 Spark 应用程序参数以获得最佳性能。

如果操作得当,调整 Spark 应用程序可以降低资源成本,同时维护关键流程的 SLA,这是本地和云环境都关心的问题。对于本地 Hadoop 环境,集群通常由多个应用程序(及其开发人员)共享。如果一个人的应用程序是资源大户,它会减慢每个人的应用程序,并冒着更高的任务失败率的风险。

随着 Spark 使用的增加,管理应用程序性能可能成为一项重大挑战。如果没有正确的方向,任何对 Spark 监控的尝试都可能很快被证明是徒劳的,而且在时间和资源上都会花费高昂的代价。这就是为什么那些缺乏关于转向哪些 Spark 指标进行优化指导的人一直在寻求专家帮助以了解这个复杂过程的原因。

大多数受访者非常关心其计算资源的资源优化,因为超过 33%(三分之一)的公司的支出超出其初始云预算的 20% 至 40%。简而言之,组织未能优化其 Spark 资源,导致超支。

在这篇博文中,我们将讨论两种 Apache Spark 优化技术:

在进入细节之前,让我们回顾一些 Spark 术语和定义:

Spark 应用程序分为多个阶段。阶段是物理执行计划中的一个步骤。它在需要随机播放(ShuffleMapStage)或阶段写入其结果并按预期终止(ResultStage)时结束。

每个阶段都分为并行执行的任务——每个分区一个任务。任务由执行者执行。

执行者是执行任务的工作者。资源(内存和 CPU 内核)在运行前由开发人员分配给执行程序。

分区是数据的逻辑块——具体来说,是弹性分布式数据集 (RDD) 的块——可以由开发人员在运行前配置。 RDD 中的分区数决定了一个阶段将执行的任务数。对于每个分区,一个任务(应用程序代码块)被提供给执行者执行。

图 1:Spark 中的数据分区

因为 Spark 应用程序可以包含许多不同类型的阶段,所以对一个阶段最佳的配置可能不适合另一个阶段。因此,Spark应用程序的Spark内存优化技术必须分阶段进行。

除了配置阶段之外,开发人员还可以控制应用程序中的任务数量(并行性)以及应用程序的执行程序大小。

使用 Spark 最大化并行性需要仔细考虑集群的核心数和分区数之间的差异。太少会导致性能低下,而太多会带来不当的间接成本。为确保并行性和效率之间的平衡,Spark 建议分区数大约是集群中核心数的三倍。

不直接的是如何选择分区的数量和执行器的大小。接下来我们将介绍它。

执行器和分区大小是开发人员通过 Spark 调优控制的两个最重要的因素。要了解它们之间的关系,我们首先需要了解 Spark 执行器如何使用内存。图 2 显示了 Spark 执行程序内存的不同区域。

图 2:Spark 执行器内存

我们可以看到有一个参数控制为执行和存储保留的执行程序内存部分:spark.memory.fraction。因此,如果我们想将 RDD 存储在内存中,我们需要我们的执行器足够大以处理存储和执行。否则,我们将面临出错的风险(在数据/计算中以及由于资源不足导致的任务失败)或应用程序运行时间过长。

另一方面,执行器的大小越大,我们可以在集群中同时运行的执行器就越少。也就是说,由于缺乏任务并行性,较大的执行程序大小经常会导致执行速度不佳。

还有为每个执行器选择 CPU 内核数量的问题,但选择是有限的。通常,1-4 个核心/执行程序的值将在实现完全写入吞吐量和不过度负担 HDFS 客户端管理并发线程的能力之间提供良好的平衡。

在处理分区和执行器时,最好的 Spark 内存优化技术之一是首先选择分区的数量,然后选择一个执行器大小来满足内存需求。

分区控制将在特定阶段的数据集上执行多少任务。在几乎没有摩擦(网络延迟、主机问题以及与任务调度和分配相关的开销)的最佳条件下,将分区数分配为集群中的可用核心数将是理想的。在这种情况下,所有任务将同时开始,同时全部完成,一步到位。

然而,真实环境并不是最佳的。在调优Spark时,我们必须考虑:

使用 Apache Spark 优化技术时,请记住这条经验法则:对于大型数据集——大于集群中单个主机上的可用内存——始终将分区数设置为集群中可用核心数的 2 或 3 倍.

但是,如果集群中的核心数量很少,而您有一个庞大的数据集,那么选择分区大小等于 Hadoop 块大小(默认情况下为 128 MB)的分区数量在以下方面具有一些优势输入/输出速度。

选择执行器大小

正如我们所讨论的,Spark 调优还涉及为您的执行程序提供足够的内存来处理存储和执行。因此,当您选择执行程序大小时,您应该考虑分区大小、整个数据集大小以及是否将数据缓存在内存中。

为了确保任务快速执行,我们需要避免磁盘溢出。当我们没有给执行者足够的内存时,就会发生磁盘溢出。这迫使 Spark 在运行时将一些任务“溢出”到磁盘。

在我们的实验中,我们发现执行程序大小的一个好的选择是不会导致磁盘溢出的最小大小。我们不想选择太大的值,因为我们会使用太少的执行器。找到避免磁盘溢出的正确大小需要进行一些试验。

图 3 显示了我们针对机器学习应用程序进行的一项实验的结果:

图 3:磁盘溢出和任务持续时间

我们多次运行同一个应用程序,只改变了执行程序的内存大小。我们将分区大小保持在 256 MB,执行程序核心数保持在 4。我们看到,在没有磁盘溢出的情况下,任务运行速度明显加快。将内存大小从 4 GB 增加一倍到 8 GB 消除了磁盘溢出,任务运行速度提高了两倍以上。但我们也可以看到,从 8 GB 到 10 GB 并没有影响任务持续时间。它并不总是如此明确,但根据我们的经验,选择不会导致磁盘溢出的最小内存大小通常是一个很好的 Spark 调优实践。

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。更多免费资源在http://www.gitweixin.com/?p=2627