`
jgsj
  • 浏览: 964489 次
文章分类
社区版块
存档分类
最新评论

分析资源管理系统的演变: 从Mesos,YARN再到Google Omega

 
阅读更多

背景

我觉得资源管理器所要处理的问题无外乎几块:资源分配的策略,资源分配的粒度,资源分配的方式,不同类型任务的调度等。看了Google新一代资源管理器Omega的论文之后,对比Mesos和YARN总结了下面一些内容。


问题分类

任何资源调度系统都将面临下面几个问题。


该怎么分离不同的调度工作?
第一,可以无视任务类型,进行均衡负载地分配。第二,专门分离一些适合不同调度工作的调度器去负责各种调度反正。第三,上两种的结合。有的系统使用多个优先级不同的任务队列来处理任务请求(YARN就是这么做的),看上去是分离了不同的调度工作,不过本质上不影响调度并行性,比如有多少调度器是可以同时去处理这些队列呢?


如何选择资源?
资源可以全局地来自于整个集群的空闲资源,也可以限制到某个子集群。前者无疑可以达到更好的控制和优化效果,并且有些挑剔的任务可以尝试去抢占其他任务的空闲资源。不过抢占这种方式带来的开销是原任务在需要这些资源的时候需要等待抢占任务对资源的释放(YARN就是支持抢占模式的)。


如何处理资源争抢(干扰)?
如果各个调度器可以自由地尝试获取需要的资源,那么部分资源就会被争抢。一种悲观的做法是让一个总领的调度者来分配所有所有的资源,底下的调度器只能负责再分配拿到手里的资源(Mesos的设计思路)。一种乐观的做法是大家都去尝试申请资源,当发现争抢时一方放弃(Omega的设计思路)。后者可以大量提高并发,但是潜在问题是调度器之间的冲突可能会很频繁。


资源分配的粒度(方式)?
主要有两种,all or nothing的原子性分配方式(Mesos实现)和增量分配方式(YARN实现)。前者的等待代价比较大,甚至发生某任务饿死,而且会让比如Mapreduce这样本身只需要部分资源就可以先开跑的任务没有必要地等待很久。后者则可能会有死锁的情况发生。


不同类型

中央调度
最原始的实现思路是一个实现了所有调度策略的单例调度者,承受所有的任务调度和资源管理(类比一代Hadoop的JobTracker)。主要问题在于难以支持丰富的策略。


静态分离的调度
将一个大的集群分割为几个次集群,以应对不同的任务和调度模式。这种情况比中央式的调度要好些,但是显然对于资源的利用率还是不够,只能是次优的。事实上,目前应该没有资源管理器按照该设计思路。


双层调度
目前主流,对静态分离调度的提升,让一个总控的协调者来动态分配资源给不同的调度者,即双层调度模式。Mesos和YARN是双层调度的代表,介绍一下各自的情况。


Mesos有一个中央资源分配者来动态分配资源给不同的frameworks(每个framework是一种计算框架,比如Spark、Hadoop,也可以是使用者实现的一个业务模块)。Mesos的资源分配是Master主动向Framework提供的,Master通过将每一份空余资源只分给一个Framework来避免冲突,并且通过主资源公平(DRF)的方式保证所有Framework公平性和合理的资源利用率。Mesos Master的这种分配控制类似悲观锁,决定了其在并发上的劣势。Framework收到Master的Offers,可以选择拒绝部分资源(资源带机器信息,具体为若干CPU数和内存数),然后再分配并调起Slave上的Executor执行任务。
Mesos比较适合短任务,并且是那种大量的执行起来比较快的任务,这些任务所需要的资源同整个集群资源相比,又是很小的这种场景。这其实又和Mesos选择的资源分配粒度有关,Mesos的资源分配是all or nothing的类似原子性的分配方式,拥有大需求量的任务有可能会被饿死,且Mesos自身对Frameworks无优先级对待。
所以Mesos适用的场景其实很明了,主要是由他的资源分配粒度(all or nothing)、分配策略(DRF)、分配控制(悲观锁)导致的。具体还可参考我前一篇文章:Mesos实战总结


YARN的第一层是ResourceMaster,每一个第二层的业务应用称为ApplicationMaster,资源按Container划分。在资源表示模型上,YARN设定的是虚拟CPU和虚拟内存。在资源管理方式上,YARN对内存资源和CPU资源采用了不同的资源隔离方案。对于内存资源,为了能够更灵活的控制内存使用量,YARN采用了进程监控的方案控制内存使用;对于CPU资源,则采用了Cgroups进行资源隔离。此外YARN对调度语义的支持更丰富,支持:请求某个特定节点上的特定资源量;请求某个特定机架上的特定资源量;将某些节点加入或移除黑名单;请求归还某些资源。在资源保证机制上,YARN采用的是增量资源分配机制,优先为应用程序预留一个节点上的资源,优点是不会发生饿死现象,但有一定的浪费。YARN支持资源抢占模型,负载轻的队列会把暂时空余的资源交给负载重的队列使用,当轻的队列收到应用,需要取回原先分配出去的资源的时候,就出现抢占。默认是不开启的,可以在配置里触发,且抢占策略是插拔式组件。YARN Scheduler policy更丰富,包括FIFO、Capacity、Fair。


共享状态调度
Google Omega使用的是基于shared state的策略。每个调度器都拥有整个集群的权限,可以自由获取资源,同时优化了并发控制来调节他们的争抢冲突。这种方式解锁了双层调度器悲观锁导致的并发限制,让每个Framework对全局资源可见。
Omega采用了基于多版本的并发访问控制方式(也称为“乐观锁”, MVCC, Multi-Version Concurrency Control)。Omega对共享状态的实现和维护方式类似多个人一起coding SVN上的一份代码。集群维护着有一份所有资源的最小单位状态列表(成为cell state)。每个调度器本地也有一份,调度器按照自己的策略选择了一些需要的资源后,会进行一次原子性的commit,如果发生冲突,就像我们提SVN代码一样,说明该资源已经被别的Scheduler拿走, 那么需要该调度器重新选择,否则提交成功的话,申请就成功了。Omega的调度器执行的操作完全是并发的,且为了避免饿死,Omega支持的也是增量的分配模式(同YARN,不同于Mesos)。Omega在其他方面的设计我就省略了,有兴趣的同学可以看Omega的论文


附上Omega论文里的一张图,对应了以上四大问题和四大类型调度器各自的特性:


总结

其实Google的Omega的实现是很类似于双层调度器的,只是省略了第一层,或者说是进化掉了这第一层,把它变成了一个全局可访问和修改的状态维护起来,增大了并发性。实际意义上的调度器们就类似于双层调度器里的第二层,可以实现自己的调度策略,可以遵循自己的分配方式去执行Task。个人认为增量的分配模式的确是较好的,因为调度器拿到资源后,再分配给task的时候,还是可以实行all or nothing的,但是如果对调度器就实行all or nothing的话,那么该调度器里的所有任务都会因此被停滞。



全文完 :)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics