spark的资源分配策略及作业调度策略

Spark有几个工具用于在计算之间调度资源。Spark运行的集群管理器(cluster manager)(主要包括 Standalone、Mesos和YARN这三种)为跨应用程序调度提供了便利,有静态分区方式和动态资源分配方式两种。 其次,在各个Spark应用内部,Spark包含一个公平调度器来调度每个SparkContext中的资源。

1. 跨应用调度

1.1 使用静态分区方式分配集群资源

所有集群管理器都可以使用的最简单的选项是资源的静态分区。 这种方式就意味着,每个Spark应用都是设定一个最大可用资源总量,并且该应用在整个生命周期内都会占住这个资源.。这是Standalone和YARN模式以及粗粒度Mesos模式中使用的方法。

1.2 动态资源分配方式

Spark提供了一种机制,可根据工作负载动态调整应用程序占用的资源。 这意味着您的应用程序可能会在资源不再使用时将资源返回给群集,并在需求时可以再次请求使用。 如果多个应用程序共享Spark群集中的资源,此功能特别有用。
此功能在默认情况下处于禁用状态,可用于所有粗粒度集群管理器,即独立模式,YARN模式和Mesos粗粒度模式。
下面介绍配置和部署方式:
要使用这一特性有两个前提条件。首先,你的应用必须设置spark.dynamicAllocation.enabled为true。其次,你必须在每个节点上启动external shuffle service,并将spark.shuffle.service.enabled设为true。external shuffle service 的目的是在移除executor的时候,能够保留executor输出的shuffle文件。启用external shuffle service 的方式在各个集群管理器上各不相同:

  1. 在Spark独立部署的集群中,你只需要在worker启动前设置spark.shuffle.service.enabled为true即可。
  2. 在Mesos粗粒度模式下,你需要在各个节点上运行$SPARK_HOME/sbin/start-mesos-shuffle-service.sh 并设置 spark.shuffle.service.enabled为true即可。
  3. 在YARN模式下,需要按以下步骤在各个NodeManager上启动:这里

动态资源分配的具体实现:
总体上来说,Spark应该在执行器(executor)空闲时将其关闭,而在后续要用时再申请。因为没有一个固定的方法,可以预测一个执行器在后续是否马上会被分配去执行任务,或者一个新分配的执行器实际上是空闲的,所以我们需要一个试探性的方法,来决定是否申请或是移除一个执行器。

  1. 请求executor的策略:
    一个启用了动态分配的Spark应用会有等待任务需要调度的时候,申请额外的executors。在这种情况下,必定意味着已有的executors已经不足以同时执行所有未完成的任务。
    Spark会分轮次来申请执行器。实际的资源申请,会在任务挂起spark.dynamicAllocation.schedulerBacklogTimeout秒后首次触发,其后如果等待队列中仍有挂起的任务,则每过spark.dynamicAllocation.sustainedSchedulerBacklogTimeout秒后触发一次资源申请。另外,每一轮申请的执行器个数以指数形式增长。例如:一个Spark应用可能在首轮申请1个执行器,后续的轮次申请个数可能是2个、4个、8个….。
    采用指数级增长策略的原因有两个:第一,应用程序应该在开始时谨慎地请求执行器,以防只需要少数的执行者就已经足够了;第二,如果一旦Spark应用确实需要申请多个执行器的话,那么可以确保其所需的计算资源及时增长。
  2. 移除executor的策略:
    移除执行器的策略就简单得多了。Spark应用会在某个执行器空闲超过 spark.dynamicAllocation.executorIdleTimeout秒后将其删除,在大多数情况下,执行器的移除条件和申请条件都是互斥的,也就是说,执行器在有等待执行任务挂起时,不应该空闲。
    非动态分配模式下,执行器可能的退出原因有执行失败或是相关Spark应用已经退出。不管是哪种原因,执行器的所有状态都已经不再需要,可以丢弃掉。但是在动态分配的情况下,执行器有可能在Spark应用运行期间被移除。这时候,如果Spark应用尝试去访问该执行器存储的状态,就必须重算这一部分数据。因此,Spark需要一种机制,能够优雅的关闭执行器,同时还保留其状态数据。要解决这一问题,就需要用到 external shuffle service ,该服务在 Spark 1.2 引入。该服务在每个节点上都会启动一个不依赖于任何 Spark 应用或执行器的独立进程,就可以优雅的来关闭executor。

2. 应用内调度

在指定的 Spark 应用内部(对应同一 SparkContext 实例),多个线程可能并发地提交 Spark 作业(job)。Spark 调度器是完全线程安全的,并且能够支持 Spark 应用同时处理多个请求(比如 : 来自不同用户的查询)。

2.1 FIFO 调度策略

默认情况下,Spark 应用内部使用 FIFO 调度策略。每个作业被划分为多个阶段(stage)(例如 : map 阶段和 reduce 阶段),第一个作业在其启动后会优先获取所有的可用资源,然后是第二个作业再申请,再第三个……。如果前面的作业没有把集群资源占满,则后续的作业可以立即启动运行,否则,后提交的作业会有明显的延迟等待。

2.2 公平(Fair)调度策略

不过从 Spark 0.8 开始,Spark 也能支持各个作业间的公平(Fair)调度。公平调度时,Spark 以轮询的方式给每个作业分配资源,因此所有的作业获得的资源大体上是平均分配。这意味着,即使有大作业在运行,小的作业再提交也能立即获得计算资源而不是等待前面的作业结束,大大减少了延迟时间。这种模式特别适合于多用户配置。 要启用公平调度器,只需设置一下 SparkContext 中 spark.scheduler.mode 属性为 FAIR 即可 :

val conf = new SparkConf().setMaster(...).setAppName(...)
conf.set("spark.scheduler.mode", "FAIR")
val sc = new SparkContext(conf)

如果启用了公平调度策略,默认情况下,各个资源池之间平分整个集群的资源,但在资源池内部,默认情况下,作业是 FIFO 顺序执行的。举例来说,如果你为每个用户创建了一个资源池,那么久意味着各个用户之间共享整个集群的资源,但每个用户自己提交的作业是按顺序执行的,而不会出现后提交的作业抢占前面作业的资源。
默认情况下,新提交的作业都会进入到默认(default)资源池中,不过作业对应于哪个资源池,可以在提交作业的线程中用 SparkContext.setLocalProperty 设定 spark.scheduler.pool 属性。示例代码如下 :

sc.setLocalProperty("spark.scheduler.pool", "pool1")

一旦设好了局部属性,所有该线程所提交的作业(即 : 在该线程中调用action算子,如 : RDD.save/count/collect 等)都会使用这个资源池。同样,如果需要清除资源池设置,只需在对应线程中调用如下代码 :

sc.setLocalProperty("spark.scheduler.pool", null)

当然这一切都是可以修改的,比如:公平调度器还可以支持将作业分组放入资源池(pool),然后给每个资源池配置不同的选项(如 : 权重)。这样你就可以给一些比较重要的作业创建一个“高优先级”资源池,或者你也可以把每个用户的作业分到一组,这样一来就是各个用户平均分享集群资源,而不是各个作业平分集群资源。下面就介绍一下具体的配置:
资源池属性是一个 XML 文件,可以基于 conf/fairscheduler.xml.template 修改,然后在 SparkConf 的 spark.scheduler.allocation.file 属性指定文件路径:

conf.set("spark.scheduler.allocation.file", "/path/to/file")

资源池 XML 配置文件格式如下,其中每个池子对应一个 元素,每个资源池可以有其独立的配置 :

<?xml version="1.0"?>
<allocations>
  <pool name="production">
    <schedulingMode>FAIR</schedulingMode>
    <weight>1</weight>
    <minShare>2</minShare>
  </pool>
  <pool name="test">
    <schedulingMode>FIFO</schedulingMode>
    <weight>2</weight>
    <minShare>3</minShare>
  </pool>
</allocations>

资源池的属性需要通过配置文件来指定。每个资源池都支持以下3个属性 :

  1. schedulingMode: 控制资源池内部的作业是如何调度的,可以是 FIFO 或 FAIR。
  2. weight: 控制资源池相对其他资源池可以分配到资源的比例。默认所有资源池的 weight 都是 1。如果你将某个资源池的 weight 设为 2,那么该资源池中的资源将是其他池子的2倍。如果将 weight 设得很高,如 1000,可以实现资源池之间的调度优先级 。 也就是说,weight=1000 的资源池总能立即启动其对应的作业。
  3. minShare: 除了整体 weight 之外,每个资源池还能指定一个最小资源分配值(CPU 个数),管理员可能会需要这个设置。公平调度器总是会尝试优先满足所有活跃(active)资源池的最小资源分配值,然后再根据各个池子的 weight 来分配剩下的资源。因此,minShare 属性能够确保每个资源池都能至少获得一定量的集群资源。minShare 的默认值是 0。
    注意,没有在配置文件中配置的资源池都会使用默认配置(schedulingMode : FIFO,weight : 1,minShare : 0)。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345