Hadoop调度器
Hadoop集群中有三种作业调度器算法,分别为FIFO调度器、公平调度器和容量调度器。
1 FIFO调度器
集成在JobTracker中的原有调度算法被称为FIFO。在FIFO调度中,JobTracker从工作队列中拉取作业,最老的作业最先。这种调度方法不会考虑作业的优先级或大小,但很容易实现,而且效率很高。
2 公平调度器
公平算法的设计思想是尽可能保证所有的作业都能够获得等量的资源份额。当系统中只有一个作业执行时,它将独占整个集群并使用所有的计算资源。而一旦有其他的作业被提交,就会有TaskTracker被释放并分配给新提交的作业,以保证所有的作业都能够获得大体相同的计算资源量。这就使得短作业能够在合理的时间内完成,同时又不会有长作业长期处于饥饿状态。
Hadoop的实现会创建一组池,将作业放在其中供调度器选择。除了提供公平共享方法外,公平算法允许赋给作业池保证(guaranteed)最小共享资源。当一个作业池包含作业时,它至少能获取到它的最小共享资源,但是当作业池不完全需要它所拥有的保证共享资源时,额外的部分会在其它作业池间进行切分。
在实际应用中,无论是作业池还是作业,都可以被赋予一定的权值并以此为依据获得相应比例的资源额度。在这种情况下,虽然作业池/作业在分享资源时不再是严格的平均分配,但是这更有利于根据用户/作业的重要程度及其实际计算需要合理地分配资源。这将有利于减少交互型作业的响应时间。
为了保证公平,每个用户被分配一个池。在这样的方式下,如果一个用户提交很多作业,那么他分配的集群资源与其他用户一样多(与他提交的工作数无关)。无论分配到池的共享有多少,如果系统未加载,那么作业收到的共享不会被使用(在可用作业之间分配)。
公平调度算法会调度运行所有的用户作业,但它也可以限制在每个作业池中能够运行的作业数量。这一点是非常重要的,因为如果一次性地运行太多的作业,会导致在MapReduce计算过程中产生过多的中间记录信息以及过多的上下文切换,这都会影响作业执行的性能。对作业池中的作业数进行限定并不会使用户提交的后续作业在执行时失败,这些作业将在调度队列中等待早先的作业执行完成。在缺省情况下,在每个作业池中对作业执行的选择是首先按照优先级高低,然后再按照提交时间先后进行排序的。
公平份额的计算是根据作业的权值将集群的资源总量划分给各个运行的作业。在缺省的情况下,作业权值的设定是基于优先级的,即每当作业的优先级升高一级,那么相应的作业权值就增加一倍。不过在公平调度算法中,作业权值的定义是可以配置的。类似的,作业池的最低资源保障也是按照权值比例分配给它所包含的各个作业。
为了选择合适的作业执行,公平调度算法会跟踪每一个作业的赤字,即一个作业在理想情况下应该获得的计算资源量(主要是计算时间)与它实际获得的计算资源量之间的差距。赤字是衡量作业调度是否公平的重要指标,如果一个作业的赤字越大,说明它在之前受到的不公平待遇越多。公平调度算法会周期性地观察各个作业中有多少任务已在上一个时间段内执行,并将该结果与它应得的资源份额作对比以更新该作业的赤字值。一旦有空闲的TaskTracker出现,它会被首先分配给当前具有最高赤字的作业使用。这其中也会出现例外,如果在系统中存在着尚未获得最低资源保障的作业池,那么从属于它的作业将会被优先调度,当然这些作业之间的选择也需要根据它们的赤字值,这样做的目的是尽可能让作业池获得能够满足其最低保障的资源份额。
抢占是通过定期检查是否有作业的资源低于其最小共享资源或低于其公平共享资源的一半,如果一个作业的资源低于其共享资源的时间足够长,它将被允许去结束其它作业的任务。所结束的任务是所有作业中那些最近运行起来的任务,以最小化被浪费的计算。
在公平调度算法的具体实现中,有两个关键:一是如何计算每一个作业的公平份额;另一个就是当有TaskTracker空闲时应该选择执行哪个作业。
在 mapred-site.xml 文件中配置公平共享。该文件会定义对公平共享调度器行为的管理。一个 XML 文件(即 mapred.fairscheduler.allocation.file 属性)定义了每个池的共享的分配。为了优化作业大小,您可以设置 mapread.fairscheduler.sizebasedweight 将共享分配给作业作为其大小的函数。还有一个类似的属性可以通过调整作业的权重让更小的作业在 5 分钟之后运行得更快 (mapred.fairscheduler.weightadjuster)。您还可以用很多其他的属性来调优节点上的工作负载(例如某个 TaskTracker 能管理的 maps 和 reduces 数目)并确定是否执行抢占。
3 容量调度器
容量调度器的原理与公平调度器有些相似,但也有一些区别。
- 容量调度适用于大型集群,它们有多个独立用户和目标应用程序。由于这个原因,容量调度能提供更大的控制和能力,提供用户之间最小容量保证并在用户之间共享多余的容量。
- 在容量调度中创建的是队列而不是池,每个队列的 map 和 reduce 插槽数都可以配置。每个队列都会分配一个保证容量(集群的总容量是每个队列容量之和)。队列处于监控之下;如果某个队列未使用分配的容量,那么这些多余的容量会被临时分配到其他队列中。
- 可以调整队列中作业的优先级。一般来说,具有高优先级的作业访问资源比低优先级作业更快,对于在同一个队列中,这种策略使用的是基于优先级的FIFO策略,但是不会抢占。
- 对队列进行严格的访问控制(假设队列绑定到一个人或组织)。这些访问控制是按照每个队列进行定义的。对于将作业提交到队列的能力和查看修改队列中作业的能力都有严格限制。
可在多个Hadoop配置文件中配置容量调度器。队列是在 hadoop-site.xml 中定义,在 capacity-scheduler.xml 中配置。可以在 mapred-queue-acls.xml 中配置 ACL。单个的队列属性包括容量百分比(集群中所有的队列容量少于或等于 100)、最大容量(队列多余容量使用的限制)以及队列是否支持优先级。更重要的是,可以在运行时调整队列优先级,从而可以在集群使用过程中改变或避免中断的情况。
4 总结
- 如果正在运行一个大型 Hadoop 集群,它具有多个客户端和不同类型、不同优先级的作业,那么容量调度器是最好选择,它可以确保访问,并能重用未使用的容量并调整队列中作业的优先级。
- 无论是小型还是大型集群,如果由同一个组织使用,工作负载数量有限,那么公平调度器也能运转得很好。公平调度可以将容量不均匀地分配给池(作业的),但是它较为简单且可配置性较低。公平调度在存在多种作业的情况下非常有用,因为它能为小作业和大作业混合的情况提供更快的响应时间(支持更具交互性的使用模型)。