随着Spark的逐渐成熟完善, 越来越多的可配置参数被添加到Spark中来, 本文试图通过阐述这其中部分参数的工作原理和配置思路, 和大家一起探讨一下如何根据实际场合对Spark进行配置优化。

由于篇幅较长,所以在这里分篇组织,如果要看最新完整的网页版内容,可以戳这里:http://spark-config.readthedocs.org/,主要是便于更新内容

schedule调度相关

调度相关的参数设置,大多数内容都很直白,其实无须过多的额外解释,不过基于这些参数的常用性(大概会是你针对自己的集群第一步就会配置的参数),这里多少就其内部机制做一些解释。

spark.cores.max

一个集群最重要的参数之一,当然就是CPU计算资源的数量。spark.cores.max 这个参数决定了在Standalone和Mesos模式下,一个Spark应用程序所能申请的CPU Core的数量。如果你没有并发跑多个Spark应用程序的需求,那么可以不需要设置这个参数,默认会使用spark.deploy.defaultCores的值(而spark.deploy.defaultCores的值默认为Int.Max,也就是不限制的意思)从而应用程序可以使用所有当前可以获得的CPU资源。

针对这个参数需要注意的是,这个参数对Yarn模式不起作用,YARN模式下,资源由Yarn统一调度管理,一个应用启动时所申请的CPU资源的数量由另外两个直接配置Executor的数量和每个Executor中core数量的参数决定。(历史原因造成,不同运行模式下的一些启动参数个人认为还有待进一步整合)

此外,在Standalone模式等后台分配CPU资源时,目前的实现中,在spark.cores.max允许的范围内,基本上是优先从每个Worker中申请所能得到的最大数量的CPU core给每个Executor,因此如果人工限制了所申请的Max Core的数量小于Standalone和Mesos模式所管理的CPU数量,可能发生应用只运行在集群中部分节点上的情况(因为部分节点所能提供的最大CPU资源数量已经满足应用的要求),而不是平均分布在集群中。通常这不会是太大的问题,但是如果涉及数据本地性的场合,有可能就会带来一定的必须进行远程数据读取的情况发生。理论上,这个问题可以通过两种途径解决:一是Standalone和Mesos的资源管理模块自动根据节点资源情况,均匀分配和启动Executor,二是和Yarn模式一样,允许用户指定和限制每个Executor的Core的数量。 社区中有一个PR试图走第二种途径来解决类似的问题,不过截至我写下这篇文档为止(2014.8),还没有被Merge。

spark.task.cpus

这个参数在字面上的意思就是分配给每个任务的CPU的数量,默认为1。实际上,这个参数并不能真的控制每个任务实际运行时所使用的CPU的数量,比如你可以通过在任务内部创建额外的工作线程来使用更多的CPU(至少目前为止,将来任务的执行环境是否能通过LXC等技术来控制还不好说)。它所发挥的作用,只是在作业调度时,每分配出一个任务时,对已使用的CPU资源进行计数。也就是说只是理论上用来统计资源的使用情况,便于安排调度。因此,如果你期望通过修改这个参数来加快任务的运行,那还是赶紧换个思路吧。这个参数的意义,个人觉得还是在你真的在任务内部自己通过任何手段,占用了更多的CPU资源时,让调度行为更加准确的一个辅助手段。

spark.scheduler.mode

这个参数决定了单个Spark应用内部调度的时候使用FIFO模式还是Fair模式。是的,你没有看错,这个参数只管理一个Spark应用内部的多个没有依赖关系的Job作业的调度策略。

如果你需要的是多个Spark应用之间的调度策略,那么在Standalone模式下,这取决于每个应用所申请和获得的CPU资源的数量(暂时没有获得资源的应用就Pending在那里了),基本上就是FIFO形式的,谁先申请和获得资源,谁就占用资源直到完成。而在Yarn模式下,则多个Spark应用间的调度策略由Yarn自己的策略配置文件所决定。

那么这个内部的调度逻辑有什么用呢?如果你的Spark应用是通过服务的形式,为多个用户提交作业的话,那么可以通过配置Fair模式相关参数来调整不同用户作业的调度和资源分配优先级。

spark.locality.wait

spark.locality.wait和spark.locality.wait.process,spark.locality.wait.node, spark.locality.wait.rack这几个参数影响了任务分配时的本地性策略的相关细节。

Spark中任务的处理需要考虑所涉及的数据的本地性的场合,基本就两种,一是数据的来源是HadoopRDD; 二是RDD的数据来源来自于RDD Cache(即由CacheManager从BlockManager中读取,或者Streaming数据源RDD)。其它情况下,如果不涉及shuffle操作的RDD,不构成划分Stage和Task的基准,不存在判断Locality本地性的问题,而如果是ShuffleRDD,其本地性始终为No Prefer,因此其实也无所谓Locality。

在理想的情况下,任务当然是分配在可以从本地读取数据的节点上时(同一个JVM内部或同一台物理机器内部)的运行时性能最佳。但是每个任务的执行速度无法准确估计,所以很难在事先获得全局最优的执行策略,当Spark应用得到一个计算资源的时候,如果没有可以满足最佳本地性需求的任务可以运行时,是退而求其次,运行一个本地性条件稍差一点的任务呢,还是继续等待下一个可用的计算资源已期望它能更好的匹配任务的本地性呢?

这几个参数一起决定了Spark任务调度在得到分配任务时,选择暂时不分配任务,而是等待获得满足进程内部/节点内部/机架内部这样的不同层次的本地性资源的最长等待时间。默认都是3000毫秒。

基本上,如果你的任务数量较大和单个任务运行时间比较长的情况下,单个任务是否在数据本地运行,代价区别可能比较显著,如果数据本地性不理想,那么调大这些参数对于性能优化可能会有一定的好处。反之如果等待的代价超过带来的收益,那就不要考虑了。

特别值得注意的是:在处理应用刚启动后提交的第一批任务时,由于当作业调度模块开始工作时,处理任务的Executors可能还没有完全注册完毕,因此一部分的任务会被放置到No Prefer的队列中,这部分任务的优先级仅次于数据本地性满足Process级别的任务,从而被优先分配到非本地节点执行,如果的确没有Executors在对应的节点上运行,或者的确是No Prefer的任务(如shuffleRDD),这样做确实是比较优化的选择,但是这里的实际情况只是这部分Executors还没来得及注册上而已。这种情况下,即使加大本节中这几个参数的数值也没有帮助。针对这个情况,有一些已经完成的和正在进行中的PR通过例如动态调整No Prefer队列,监控节点注册比例等等方式试图来给出更加智能的解决方案。不过,你也可以根据自身集群的启动情况,通过在创建SparkContext之后,主动Sleep几秒的方式来简单的解决这个问题。

spark.speculation

spark.speculation以及spark.speculation.interval,spark.speculation.quantile, spark.speculation.multiplier等参数调整Speculation行为的具体细节,Speculation是在任务调度的时候,如果没有适合当前本地性要求的任务可供运行,将跑得慢的任务在空闲计算资源上再度调度的行为,这些参数调整这些行为的频率和判断指标,默认是不使用Speculation的。

通常来说很难正确的判断是否需要Speculation,能真正发挥Speculation用处的场合,往往是某些节点由于运行环境原因,比如CPU资源由于某种原因被占用,磁盘损坏导致IO缓慢造成任务执行速度异常的情况,当然前提是你的分区任务不存在仅能被执行一次,或者不能同时执行多个拷贝等情况。Speculation任务参照的指标通常是其它任务的执行时间,而实际的任务可能由于分区数据尺寸不均匀,本来就会有时间差异,加上一定的调度和IO的随机性,所以如果一致性指标定得过严,Speculation可能并不能真的发现问题,反而增加了不必要的任务开销,定得过宽,大概又基本相当于没用。

个人觉得,如果你的集群规模比较大,运行环境复杂,的确可能经常发生执行异常,加上数据分区尺寸差异不大,为了程序运行时间的稳定性,那么可以考虑仔细调整这些参数。否则还是考虑如何排除造成任务执行速度异常的因数比较靠铺一些。

当然,我没有实际在很大规模的集群上运行过Spark,所以如果看法有些偏颇,还请有实际经验的XD指正。

Spark 性能相关参数配置详解-任务调度篇的更多相关文章

  1. Spark 性能相关参数配置详解-shuffle篇

    随着Spark的逐渐成熟完善, 越来越多的可配置参数被添加到Spark中来, 在Spark的官方文档http://spark.apache.org/docs/latest/configuration. ...

  2. Spark 性能相关参数配置详解-压缩与序列化篇

    随着Spark的逐渐成熟完善, 越来越多的可配置参数被添加到Spark中来, 本文试图通过阐述这其中部分参数的工作原理和配置思路, 和大家一起探讨一下如何根据实际场合对Spark进行配置优化. 由于篇 ...

  3. Spark 性能相关参数配置详解-Storage篇

    随着Spark的逐渐成熟完善, 越来越多的可配置参数被添加到Spark中来, 本文试图通过阐述这其中部分参数的工作原理和配置思路, 和大家一起探讨一下如何根据实际场合对Spark进行配置优化. 由于篇 ...

  4. druid 参数配置详解

    druid 参数配置详解 */--> druid 参数配置详解 Table of Contents 1. 初始化连接 2. 参数配置及说明 3. 注意事项 3.1. 底层连接 3.2. 空闲检查 ...

  5. Nginx.conf参数配置详解

    Nginx的配置文件nginx.conf配置详解如下: user nginx nginx; #Nginx用户及组:用户 组.window下不指定 worker_processes 8; #工作进程:数 ...

  6. logback 常用参数配置详解

    logback 常用配置详解(二) <appender> <appender>: <appender>是<configuration>的子节点,是负责写 ...

  7. HDFS之三:hdfs参数配置详解

    1.hdfs-site.xml 参数配置 – dfs.name.dir – NameNode 元数据存放位置 – 默认值:使用core-site.xml中的hadoop.tmp.dir/dfs/nam ...

  8. KingbaseES V8R6集群同步模式synchronous参数配置详解

    如下图所示: 集群数据同步原理说明: synchronous参数配置测试: 集群节点信息: ID | Name | Role | Status | Upstream | repmgrd | PID | ...

  9. JVM参数配置详解-包含JDK1.8

    堆大小设置    JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:6 ...

随机推荐

  1. 关于json格式字符串解析并用mybatis存入数据库

    园子里面找了很多关于json解析后存入数据库的方法,不是太乱,就是没有写完,我下面的主题代码多是受下面两位的启发,请按顺序查看 http://www.cnblogs.com/tian830937/p/ ...

  2. jdk、jre、JVM的简单区别与联系

    2015-10-20 23:08:52 (1)jdk Java development toolkit(开发工具包),JDK是整个JAVA的核心,包括了Java运行环境jre(Java Runtime ...

  3. 理想中的 PCB 文件格式

    理想中的 PCB 文件格式 因为平时写代码使用 git,在画 PCB 也使用 git 来管理 PCB 文件. 但是 PCB 文件是二进制的,所以在比较时非常麻烦. 虽然 PCB 文件可以导出 文本文件 ...

  4. 1.JMeter===添加响应断言

    断言即Lr中的检查点,我们在进行测试时,需要对每次请求测试的返回做检验 1.以百度做案例,添加线程组==添加HTTP请求==添加查看结果树 2.在HTTP请求下添加响应断言 注:模式匹配规则,比较常用 ...

  5. sqlserver2008事务日志已满

    --将数据库设为简单模式.日志文件自动断开. alter database CustomerInfoProject set recovery simple --查看日志文件状况  use Custom ...

  6. 【转载】Leaflet 中文api

    L.Map API各种类中的核心部分,用来在页面中创建地图并操纵地图. 使用 example // initialize the map on the "map" div with ...

  7. 数组与指针的区别,以及在STL中传递数组/指针

    数组和指针在作为实参传入T[] 或T*的形参时没有区别 void f(int pi[]) { cout << sizeof(pi) << endl; } int a[5] = ...

  8. free 命令结果完全剖析

    free 命令结果完全剖析 total 总物理内存大小. used 已分配的大小,注意,对操作系统来说任何被使用的内存都是used. free 未被分配的物理内存大小. shared 共享内存大小,主 ...

  9. var与Javascript变量隐式声明

    在JavaScript中,var用来声明变量,但是这个语法并不严格要求,很多时修改,我们可以直接使用一个变量而不用var声明它.var x = "XX"; y ="xxx ...

  10. Oracle段高水位(HWM, high water mark)问题

    Oracle对表做全表扫描的时候 ,会扫描完HWM以下的数据块.如果某个表delete(delete操作不会降低高水位)了大量数据,那么这时对表做全表扫描就会做很多无用功,扫描了一大堆数据块,最后发现 ...