在Apache Spark中进行性能调优

“对于数据工程师而言,Apache Spark 上的性能调优”

這本書只是摘譯,不能保證內容的準確性。請參考原文以獲得準確的內容。

该书是作为Data Science Blogathon的一部分而发布的。

动力

在解决Spark应用程序调优问题时,我花了很多时间来理解Spark Web UI的可视化。对于初学者来说,仅仅通过这些可视化很难直观地理解问题。虽然存在很多关于Spark性能的优秀资源,但这些信息零散分布。因此,我认为应该创建文档并分享自己的学习经验。

目标读者和所获得的见解

这篇文章假设读者对Spark的概念有基本的理解。本文将帮助初学者从Spark Web UI中识别应用程序执行时的性能问题。我们只关注从UI中无法明确了解的信息或通过不清晰的信息进行推断。请注意,本文没有提供可以从Spark Web UI中解释的全面信息列表,而是只针对与我的项目相关并足够通用化的内容进行介绍。

Spark 网页用户界面

只有在应用程序运行时才能使用 Spark Web UI。要分析过去的运行结果,需要启用一个历史服务器来存储事件日志,以便将数据显示在Web UI中。

Spark Web UI会在以下标签中显示与您的应用程序相关的有用信息。

    • Executors

 

    • Environment

 

    • Jobs

 

    • Stages

 

    Storage

在本书的剩余部分中,将按照每个标签所提供的直觉进行逐一解释。

执行者选项卡

提供所有执行者执行任务的信息。

图1:执行者选项卡摘要

从图1中,我们可以看到有一个拥有2个核心和3GB内存的驱动程序和5个执行器正在运行。

在被标记为红色的方框中,我们可以看到一个节点群集正在过度处理任务,而其他节点相对处于空闲状态,造成了不平衡的分布。

在被标注为蓝色方框的盒子中,显示了输入大小为487.3MB。现在,该应用程序已针对大小为83MB的数据集运行。输入数据大小包括加载的原始数据集和在节点之间传输的洗牌数据。这表明在应用程序内有大量数据(约400MB)被洗牌。

环境选项卡

存在很多用于控制和微调应用程序的spark属性。这些属性可以在提交作业或创建上下文对象时进行配置。除非显式添加属性,否则属性将不会应用。我们误解了默认情况下这些属性将被应用,除非我们明确设置它们。可以在环境选项卡中查看所有应用的属性。如果属性未在此处显示,则意味着该属性根本未应用。

工作选项卡

任务与以图2所示的有效非循环图(DAG)中整理的Resilient Distributed Dataset(RDD)的依赖关系链相关联。从DAG的可视化中可以看出,有多个阶段被执行,有很多阶段被跳过。默认情况下,除非显式持久化/缓存,否则Spark不会重用在阶段上计算出来的阶段。被跳过的阶段是用灰色标记的缓存阶段,计算出的值被存储在内存中,并在访问HDFS后不会重新计算。通过一眼看到DAG的可视化,就足以理解RDD的计算是否正在进行,以及是否使用了缓存阶段。

舞台选项卡

提供了应用程序执行任务级别的详细视图。阶段显示了并行执行的处理段落,由各个任务执行。任务与数据分区之间存在一对一的映射,并且每个数据分区对应一个任务。可以通过Spark Web UI深入查看作业、特定阶段和阶段的所有任务。

舞台提供了有关任务的DAG可视化、事件时间轴、摘要/汇总指标等执行过程的优秀概览。

我喜欢查看事件时间线来分析任务。这些时间线以图形方式提供了对所花费时间的详细表达,能够快速推断舞台的执行情况以及如何进一步改善执行时间。

例如,可以从图3中得出以下推论。

    1. 数据被分割成了15个分区,即执行了15个任务(用15条绿线表示)。

 

    1. 任务在具有2个执行器的3个节点上执行。

 

    1. 当最长的任务完成时,阶段才算完成。在最长的任务完成之前,其他执行器将保持空闲状态。

 

    1. 一些任务非常快速完成,而另一些任务需要很长时间,这表明数据没有很好地分区。

 

    在这个阶段中,时间大部分没有被调度程序的延迟或序列化浪费掉,这是一个好趋势。

通过观察图4,我们可以得出数据没有很好地分散,而是被不必要地分区。从评估指标中,我们可以确认任务的调度需要比实际执行时间更多的时间。时间轴上绿色部分的比例越大,意味着阶段计算处理更加高效。

在工作中,包含的阶段数越少越好。当数据被洗牌时,会添加新的阶段。由于洗牌的代价很高,因此您的程序应该尽量减少所需的阶段数。

输入数据的大小

需要注意的另一个重要洞察是输入数据的大小被打乱。一个目标是减小这些打乱数据的大小。

在图5中,用MB表示数据移动的阶段。这是改善代码以减少阶段之间数据交换大小的提示。例如,对于某个特定事件x的数据应用过滤器,并且结果RDD的所有行的事件列都成为x,这可能会导致冗余。为了减少在洗牌操作期间传输的附加信息,可能需要从经过过滤的数据RDD中删除此列。

储存标签

只有使用persist()或cache()进行持久化的RDD才会显示在存储选项卡中。为了更容易理解,您可以使用setName()在存储时为RDD分配一个名称。只有您要持久化的RDD会显示在存储选项卡中,并且通过指定自定义名称可以更容易地区分它们。

总结

本书介绍了从Spark Web UI获取有助于识别问题的洞察信息,例如被洗牌的数据大小、阶段执行时间以及RDD重新计算由于缺乏缓存而引起的问题。通过理解自己的数据和应用程序,可以通过执行UI推断出理想数据分布和所需的分区数。对于集群中某个节点的过载与其他节点相比,这也是可以通过UI观察到的改进领域。Apache Spark性能调优文章中讨论了针对这些问题的解决方案。

广告
将在 10 秒后关闭
bannerAds