大数据工程师面试题 - Spark 基础调优(五)

调优概述

在开发完Spark作业之后,就该为作业配置合适的资源了。Spark的资源参数,基本都可以在spark-submit命令中作为参数设置。很多Spark初学者,通常不知道该设置哪些必要的参数,以及如何设置这些参数,最后就只能胡乱设置,甚至压根儿不设置。资源参数设置的不合理,可能会导致没有充分利用集群资源,作业运行会极其缓慢;或者设置的资源过大,队列没有足够的资源来提供,进而导致各种异常。总之,无论是哪种情况,都会导致Spark作业的运行效率低下,甚至根本无法运行。因此我们必须对Spark作业的资源使用原理有一个清晰的认识,并知道在Spark作业运行过程中,有哪些资源参数是可以设置的,以及如何设置合适的参数值。

Spark作业基本运行原理:

当我们使用spark-submit提交一个Spark作业后,作业会启动一个对应的Driver进程,Driver进程的位置取决于我们使用的部署方式。Driver进程的任务是占用一定数量的内存和CPU核心,然后申请作业需要的资源。

资源申请

Driver进程首先向集群管理器申请资源,这些资源包括在各个工作节点上启动必要数量的Executor进程,每个Executor进程都拥有特定数量的内存和CPU核心。

任务调度和执行

获得资源后,Driver进程根据我们编写的作业代码将作业分拆成多个stage,每个stage包含一批task。Driver进程将这些task分配到各个Executor进程执行。task是执行我们编写的一段代码片段的计算单元,每个task处理不同的数据。

stage及数据处理

作业以shuffle类算子划分stage,每个stage的所有task完成后,Driver启动下一个stage。下一个stage的task读取上一个stage的输出结果作为输入。当代码执行cache/persist等持久化操作时,每个task计算出的数据也会保存到Executor进程的内存或保存在节点的磁盘文件中。

Executor内存分布

Executor的内存主要有三部分;执行我们的代码默认占用20%的内存,shuffle过程中task对结果进行聚合操作占用20%的内存,RDD持久化占用60%内存。

task执行速度

task的执行速度和每个Executor进程的CPU核心数量直接相关。如果CPU核心数量充足,并且分配给的task数量合理,通常可以快速高效地执行这些task。

资源参数调优

了解完了Spark作业运行的基本原理之后,对资源相关的参数就容易理解了。所谓的Spark资源参数调优,其实主要就是对Spark运行过程中各个使用资源的地方,通过调节各种参数,来优化资源使用的效率,从而提升Spark作业的执行性能。以下参数就是Spark中主要的资源参数,每个参数都对应着作业运行原理中的某个部分,我们同时也给出了一个调优的参考值。

  • num-executors: 这个参数设置Spark作业的执行器(Executor)数量。默认情况下,如果不设置,系统只会启动少量的Executor进程,影响作业运行速度。一般情况下,设置50-100个Executor进程比较合适。
  • executor-memory: 这个参数设置每个Executor进程的内存,对Spark作业的性能有直接影响。常规来说,设置4G - 8G内存是比较合适的,但具体值还需要根据队列的最大内存限制来决定。
  • executor-cores: 这个参数用于设置每个Executor进程的CPU core数量,它决定了每个Executor进程并行执行任务的能力。理想值在2-4个,但具体数量需要根据队列的最大CPU core限制和Executor数量来确定。
  • driver-memory: 这个参数用于设置Driver进程的内存。常规来说,不设置也可以,或者设置1G内存。只有在使用collect算子将RDD的数据全部拉取到Driver上处理时,需要确保Driver的内存足够大。
  • spark.default.parallelism: 这个参数设置了每个stage的默认task数量,对于Spark作业性能非常关键。推荐的task数量设置为500-1000个。Spark会根据HDFS的block数量设置task数量,如果task数量偏少,前面的Executor设置参数就会失效。
  • spark.storage.memoryFraction: 这个参数用于设置RDD持久化数据在Executor内存中的占比,默认值是0.6。如果Spark作业中有较多的RDD持久化操作,该参数的值可以适当提高一些。
  • spark.shuffle.memoryFraction: 这个参数用于设置shuffle操作过程中,进行聚合操作时能够使用的Executor内存的比例,默认值是0.2。如果Spark作业中的RDD持久化操作较少,shuffle操作较多,应降低持久化操作的内存占比,提高shuffle操作的内存占比比例。

资源参数参考示例以下是一份spark-submit命令的示例,大家可以参考一下,并根据自己的实际情况进行调节:

./bin/spark-submit \
  --master yarn-cluster \
  --num-executors 100 \
  --executor-memory 6G \
  --executor-cores 4 \
  --driver-memory 1G \
  --conf spark.default.parallelism=1000 \
  --conf spark.storage.memoryFraction=0.5 \
  --conf spark.shuffle.memoryFraction=0.3 \

根据实践经验来看,大部分Spark作业经过本次基础篇所讲解的开发调优与资源调优之后,一般都能以较高的性能运行了,足以满足我们的需求。但是在不同的生产环境和项目背景下,可能会遇到其他更加棘手的问题(比如各种数据倾斜),也可能会遇到更高的性能要求。为了应对这些挑战,需要使用更高级的技巧来处理这类问题。在后续的《Spark性能优化指南——高级篇》中,我们会详细讲解数据倾斜调优以及Shuffle调优。

大家好,我是大数据欧老师,就职于互联网某头部大厂,超过 8 年的大数据从业经历。如果你有面试大数据工程师的打算,欢迎找我聊一聊!

#大数据##大数据工程师##大数据知识体系##大数据面试##大数据面经#

解决职场真实面试问题,分享同学真实成功案例,欢迎订阅关注!

全部评论

相关推荐

点赞 5 评论
分享
牛客网
牛客企业服务