我一直对关系数据库有很好的接触,后来又接触了像 Spark 这样的分布式系统。最初,我深入研究了 DBMS,既设置复杂的查询、管理,又主要是如何为 DBMS 组合一个执行脚本。当我开始更多地使用 Spark,后来又使用 Databricks 时,最初我在必须构建的场景中没有遇到性能问题,但随着大数据领域真正成为大数据,我开始在例程中遇到性能问题,每个例程都会增加 30%一周,这让我寻找 Spark 如何“在幕后”工作,主要是因为我已经知道 DBMS 是如何工作的,这帮助我理解了我将在这里带来的一些概念。
让我们保持简短,因为我希望本文重点关注性能分析场景、技术和最佳实践。
该组件是Spark的基础,它负责内存管理、任务、故障恢复、I/O管理,换句话说,它操作RDD。因此,他是一个拥有很大一部分集群的家伙。
这个组件是spark生态系统(集群)真正的worker,它是接收写入或读取命令(任务)的组件,可以在磁盘上,也可以在内存上,也可以在两者上(稍后我会解释为什么会出现这种情况)播放)。
Workers 对于那些已经熟悉分布式计算的人来说就是字面上的意思,它们是集群的节点,所以它是我上面提到的执行器的“托管”,每个工作器可以包含一个或多个执行器。它负责管理分配给执行者的资源,就好像执行者是助手,工人是仓库工人一样。如果他是他汇报的仓库管理员怎么办?
这是经理,他为工作人员管理资源(内存和CPU),他决定每个应用程序将有多少执行者以及将分配多少资源,他管理他的''发送的任务boss',我将在下面进一步解释,由于它的职责更高,它还监视集群的状态以从故障中恢复,并根据需要重新分配任务。 (注意:集群管理器有多种类型:Yarn、mesos、kubernetes 以及最简单的独立集群管理器)。
嗯,这是老板或网关,我说网关是因为任何 Spark 应用程序都会经过它,它是允许应用程序与集群交互的东西,即工作人员和执行者,它允许和管理工作人员之间的任务,通过这种方式,它在配置、执行器数量和内存等资源方面管理整个应用程序。您需要知道任务是如何执行的吗?在这里与这位老板交谈。
所以,以一种说明性的方式:
当我与关系银行方面合作时,出现性能问题,主要是在应用程序中的过程或函数或查询中,我分析了以下几个方面:
嗯,我想就是这样,现在这些点与 Apache Spark 有什么共同点?
总结一下每一个是什么,尽管有名字,你已经可以得到一个想法:
逻辑计划:
将原始查询表示为一系列逻辑运算。它是查询的抽象形式,而不考虑它的实际执行方式。包括有关将要执行的操作的信息,例如过滤、选择、连接、聚合以及错误的“小事情”,哈哈。
物理平面:
详细说明 Spark 将如何实际执行查询。这包括操作顺序以及将使用哪些算法(例如 DBMS 算法)。它可能包括有关数据如何在执行器之间分区和分配的详细信息。
执行策略:
物理平面可以显示 Spark 可以使用的不同执行策略,例如“Broadcast Join”或“Shuffle Hash Join”,具体取决于操作和数据大小。我也会解释一下执行计划的主要算法,冷静一下...
预计费用:
尽管并不总是显示,但某些计划可能包括计划不同部分的成本估算,帮助您了解处理的哪一部分可能成本最高。
我们有一个文本形式的“根”形式,使用explain()命令,它将有一个类似于下面的输出,显示一个简单的过滤器和一个数据框:
== 物理计划==
*(2) 过滤器(值 > 1)
- *(2) 项目 [名称#0,值#1]
- *(1) 扫描现有RDD[名称#0, 值#1]
客观地,我们可以通过界面、通过 Spark UI 来分析它,在 Databricks 中我们可以访问它,无论是在单元执行中、在作业中还是在集群中。在 Apache Spark 中,它直接是默认端口 4040 上的 IP。
Spark UI 分为几个有用的部分:
作业:显示应用程序中执行的所有作业的列表。每个作业对应于代码中的一个操作。
阶段:显示组成每个作业的阶段。阶段是可以并行执行的工作细分。
任务:详细说明每个阶段内的各个任务,包括有关任务执行时间和状态的信息。
存储:提供有关 RDD(弹性分布式数据集)的内存和存储使用情况的信息。
环境:显示运行时环境属性,包括 Spark 配置和系统变量。
Executors:显示为应用程序创建的执行器的信息,包括内存使用情况、磁盘使用情况和性能统计信息。
在这里我是有等级制度的,好吗?这就是事情发生的顺序。
我想要将图像放在屏幕上!!
首先,我将解释 Spark UI 界面和执行计划中演示的主要算法,无论是逻辑计划还是物理计划:
注意:记住这里的数据集与 Spark 表相同;)
1。让我们从最著名的扫描开始:
2。加入(这个给了一些B.O):
Broadcast Hash Join:当其中一个数据集足够小,可以传输到集群中的所有节点时使用,避免 Shuffle(我会详细解释这个东西,但简而言之,这是一种数据 shuffle 操作最终加入)。
随机散列连接:两个数据集(如果您愿意,也可以是表)都会被随机排列,以便相应的键位于同一分区中。当数据集很大,无法传输到其他节点时使用。
排序合并连接:要求在连接之前对两个数据集进行排序。对于已经分区和排序的大型数据集来说它是有效的,也就是说,连接是通过分区和排序的列完成的(例如 df.write.partitionBy("coluna1").sortBy("coluna2").parquet("路径/到/保存/分区")
3。聚合(总和、计数、分组等...):
HashAggregate:使用哈希表来聚合数据。它对于适合内存的大型数据集非常有效。
排序聚合。对数据进行排序后进行聚合。当数据无法放入内存时使用。
4。随机播放(小心这个家伙):
5。交换:
6。项目:
7。筛选:
8。排序:
上面的所有这些算法都可以像我之前所说的通过explain()命令来观察。
1。 Join 和 GroupBy 操作
join() 和 groupByKey() 等操作通常会触发 shuffle,从而在分区之间重新分配数据。这可能会导致:
高磁盘 I/O 使用率:Shuffle 会生成许多中间文件,这会使执行器的本地磁盘饱和。
高网络负载:执行器之间传输的数据量可能很大,具体取决于所需的连接数量(映射器数量乘以减速器数量)
缓解
在 Spark UI 中随机排列指标:
shuffle 的工作原理以及成本高昂的原因:
由于 Databricks、Jupyter Notebook 和 Google Colab 的广泛流行,绝大多数人都使用 Notebook 进行工作。因此,将每个查询或转换划分为单独的单元格,这样可以更轻松地识别哪个部分是性能问题。把一切放在一起,有好几个工作,很难知道是哪个阶段。
使用合并而不是覆盖,我知道这需要更多工作,但它更具逻辑性和执行力,因为合并将使用比在数据湖中再次“转储”覆盖整个表更少的 I/O。
使用cache()或persist()将中间数据存储在内存中,特别是当它将在多个操作中重用时。这可以减少重新计算时间并提高性能。
如果你不知道,Spark 运行在 JVM 上,因此它本身就是 Java,当你使用 Python 创建著名的 UDF - 用户定义函数时,你为 Spark 留下了一种“黑匣子”,阻止了它自动优化。只要有可能,请使用针对性能进行优化的内置 Spark SQL 函数。
嗯,我想我已经写下了我想到的一切,我喜欢写文章,因为它可以帮助我记住一些场景。我打算录制一个视频来展示这一切,在实践中使用一些公开数据,我可能会在 Kaggle 上获取它,所以在 LinkedIn 上关注我,以了解与数据、人工智能和软件开发世界相关的一切
--> https://www.linkedin.com/in/airton-lira-junior-6b81a661
在 LinkedIn 上关注我,给我动力,我喜欢反馈,并且我也完全愿意改善知识共享。
如果您已经读到这里,恭喜您!!!我希望它能克服所有性能问题。在下一篇文章中,我将介绍 Databricks 的优势,请在 LinkedIn 上关注我以了解详情。谢谢!!
以上是了解和应用 Apache Spark 调优策略的详细内容。更多信息请关注PHP中文网其他相关文章!