不同应用之间的资源调度
standalone集群 默认是simple FIFO scheduler,也就是说允许接入的应用使用全量的cpu和mem。如果想要在多用户下限制,需要设置参数来控制每个应用占有的资源数,比如System.setProperty("spark.cores.max","10"), System.setProperty("spark.executor.memory ","10g")
在standalone模式,yarn模式,和粗粒度的mesos模式下,都是使用static partition的方式,设定每个应用占用的cpu和mem数
mesos还有一种模式(默认细粒度的模式)是dynamic sharing CPU cores,但是mem还是固定独立分配的。这种模式可能会带来不可预估的延迟,因为每个node要取回自己的core来work的时候,需要等待释放。
以上模式里都不包含可以共享mem的方式。如果要共享内存里的数据的话,一方面可以用shark的jdbc接口,处理sql的时候同时共享某些RDD;另一方面,在未来的发布版本里,Tachyon会提供另一种方式共享RDDs。
同一个应用下的资源调度
在同一个SparkContext里,jobs是可以并行跑的,spark的调度器是线程安全的。
但是默认的调度器处理jobs是FIFO的。每个job有若干个stages(map和reduce的阶段),如果前面的stage把mem和cpu占满了,那后续来的job里的stage可能就卡住不能跑了。所以spark-0.8里出了fair scheduler这个新的调度模式,对jobs的tasks采用轮询的方式,短的任务在长任务跑的情况下也可以得到资源并行进行,适合多用户使用的情况
Fair Scheduler提供pool的概念,pool可以设置weight。比如在一个线程上设置(启动一个SparkContext前)
- context.setLocalProperty("spark.scheduler.pool", "pool1")
指定了一个叫pool1的pool,之后该线程下进行的jobs就都属于这个pool了。且默认的pool平均分享cpu和mem总量(weight默认是1,可以调),每个pool内的job按FIFO模式(pool内job之间是FIFO或Fair是可以设置的)。这样的话,比如5个user每人一个默认的pool,那么大家享有的资源量是一样的,各自执行的任务还是会按先后顺序执行。pool除了可以设置weight和改变内部mode外,还可以设置minShare,指这个pool可以额外分享几个cpu cores,默认是0。Fair Scheduler每次都会尝试去满足active pools的minshare量。
以上每个pool的参数和pool名字(种类)可以在一个xml里声明,然后在启动Context的时候使用:
- System.setProperty("spark.scheduler.allocation.file", "/path/to/file")
下图为源码里和这部分相关的类图: