在Hadoop生态系统中,YARN(Yet Another Resource Negotiator)作为核心资源管理平台,其架构设计将计算资源管理与作业调度解耦,形成了"全局资源管理器(ResourceManager)+节点管理器(NodeManager)+应用管理器(ApplicationMaster)"的三层架构体系。其中ResourceManager的调度器模块(Scheduler)承担着集群资源分配的中枢职能,通过动态协调容器(Container)的分配与回收,实现多租户环境下计算资源的有效利用。
资源调度器在YARN架构中主要实现三大核心功能:首先是对集群所有节点资源的全局视图维护,通过NodeManager的心跳机制实时收集各节点的CPU、内存等资源可用量;其次是按照预设策略对资源请求进行仲裁,决定将哪些Container分配给特定应用;最后还需要处理资源抢占和回收逻辑,确保高优先级任务能够及时获取所需资源。这种设计使得YARN能够支持多种计算框架(如MapReduce、Spark、Flink)并发运行,同时保证集群资源的合理分配。
早期YARN仅提供FIFO Scheduler这种简单的先进先出调度器,其单队列设计虽然实现简单,但无法满足多用户共享集群时的公平性需求。随着企业应用场景的复杂化,逐渐衍生出两种主流的调度器变体:
这两种调度器虽然策略不同,但都实现了基础的资源共享机制:包括基于队列的资源隔离、用户限制管理、资源超额申请处理等共性功能。它们也都支持通过配置文件(fair-scheduler.xml或capacity-scheduler.xml)定义复杂的队列层次结构,并允许管理员动态调整队列参数而不需重启集群。
当ResourceManager收到应用提交请求时,所有类型的调度器都遵循相似的决策链条:首先根据提交用户或应用标签确定目标队列,然后在队列内部按照既定策略排序待处理的应用请求,最后结合节点资源报告决定具体的Container分配方案。这个过程中,调度器需要持续跟踪各队列的资源使用量、运行中的应用数等关键指标,为后续调度决策提供依据。
值得注意的是,现代YARN调度器都实现了动态资源配置能力。例如当某个队列资源利用率持续低于阈值时,调度器可以临时将闲置资源分配给其他队列使用,这种设计显著提升了集群整体利用率。同时,它们也都支持资源抢占机制,当高优先级任务需要资源时,可以通过终止低优先级任务的Container来快速释放资源。
1. 队列选择阶段 采用基于队列资源利用率的动态评估算法。系统会实时计算每个队列的"资源使用率比值"(实际使用资源/队列容量),优先选择比值最低的队列进行资源分配。例如:
2. 应用选择阶段 在选定队列内部,采用改进的FIFO策略与用户资源限制相结合的混合机制。具体执行流程包括:
3. Container分配阶段 采用增量式资源分配算法,每次分配时会综合考虑:

CapacityScheduler支持树状队列层级结构,通过"root.子队列.孙队列"的路径表达式定义队列关系。典型生产环境配置包含以下关键参数:
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>prod,dev,test</value> <!-- 第一级队列 -->
</property>
<property>
<name>yarn.scheduler.capacity.root.prod.queues</name>
<value>bi,streaming</value> <!-- 第二级队列 -->
</property>
<property>
<name>yarn.scheduler.capacity.root.prod.bi.capacity</name>
<value>60</value> <!-- 队列容量占比 -->
</property>队列特性配置包含三个关键维度:
当集群存在空闲资源时,CapacityScheduler通过以下机制实现资源动态分配:
为防止单个用户垄断队列资源,调度器实施双重限制:
现代CapacityScheduler版本通过以下扩展增强管理能力:
实际案例中,某电商平台采用三级队列结构实现资源隔离:
这种设计在保证关键业务SLA的同时,实现了集群资源利用率从原有55%提升至82%的优化效果。
FairScheduler作为YARN的核心调度器之一,其设计哲学源于"公平共享"理念。在架构层面,它采用分层队列结构(FSParentQueue和FSLeafQueue),每个队列通过权重(weight)参数定义资源获取比例。值得注意的是,FairScheduler管理的资源单位并非简单的内存或CPU,而是通过ResourceCalculator抽象实现的多维度资源计算,这使得它能够同时处理内存、CPU等异构资源类型的分配。
队列层级中的关键角色包括:
这种分层结构使得资源分配能够按照组织架构进行逻辑划分,同时保持各层级间的资源隔离性。每个队列维护着两组关键指标:Steady Fair Share(理论配额)和Instantaneous Fair Share(动态配额),前者基于静态配置计算得出,后者则根据运行时状态动态调整。
资源分配的核心排序逻辑由FairShareComparator实现,该比较器通过多维度指标决定任务调度优先级。其排序规则遵循以下层次结构:
这种三级判断机制确保了资源分配的基线公平性。例如,假设队列A配置了minShare=10GB但当前仅获得5GB,而队列B已获得其minShare,则无论fairShare使用率如何,队列A都会优先获得资源分配。

具体实现上,FairShareComparator通过ComputeFairShares类完成实际计算。计算过程会先排除"固定资源"(Fixed队列),包括:
这种排除机制有效避免了无效调度开销,提升了整体调度效率。
FairScheduler的资源分配具有显著的动态适应特征,主要体现在:
公平份额动态调整 每个心跳周期(默认500ms)都会重新计算各队列的Instantaneous Fair Share。计算时考虑:
这种动态调整使得系统能够快速响应负载变化。例如当某个队列的应用突然终止,其释放的资源会在下一个周期自动分配给其他需求队列。
资源抢占机制 当队列长期低于其fairShare时,调度器会触发温和的资源抢占(通过ContainerPreemptor实现)。抢占策略采用"最小伤害原则":
这种机制既保证了资源分配的长期公平性,又最大限度减少了任务中断带来的性能损耗。
FairScheduler通过以下设计实现公平与效率的微妙平衡:
延迟调度优化 为提升数据本地性,允许应用短暂等待(默认10s)节点本地资源,而非立即分配跨节点资源。这种"有限等待"策略在公平性让步与执行效率间取得平衡,实测可降低30%以上的网络传输开销。
资源归还策略 当应用实际使用量低于分配量时,采用渐进式资源归还:
这种设计避免了频繁的资源分配震荡,维护了集群稳定性。测试表明,相比立即回收策略,这种方式能减少约40%的AM重试请求。
权重动态调整 管理员可配置队列的dynamicWeight参数,使得队列权重能根据历史使用模式自动调节。例如长期低负载的队列会获得渐进式权重提升,这种设计防止了"资源饥饿"现象,特别适合突发负载场景。
在实际部署中,以下配置项对资源分配行为产生关键影响:
minShare与maxShare的联动
fairSharePreemptionTimeout 这个关键参数(默认30s)控制抢占触发时机:
allowUndeclaredPools 启用该参数(默认false)时,系统会自动创建未声明队列,适合动态环境。但会带来两个副作用:
针对大规模集群的调优经验表明:
心跳间隔权衡
异步调度优化 启用yarn.scheduler.fair.assignmultiple(默认true)允许单次心跳分配多个Container,可降低20%-50%的调度延迟。但需要配合设置:
<property>
<name>yarn.scheduler.fair.max.assign</name>
<value>3</value> <!-- 每次心跳最大分配数 -->
</property>内存计算优化 对于内存密集型负载,建议启用DominantResourceCalculator:
<property>
<name>yarn.scheduler.fair.resource-calculator</name>
<value>org.apache.hadoop.yarn.util.resource.DominantResourceCalculator</value>
</property>这能更准确反映应用的真实资源需求,避免CPU空闲但内存耗尽导致的假性资源不足。
CapacityScheduler采用百分比定义队列资源,同一父队列下子队列的容量总和必须严格等于100%。这种设计在集群扩容时会自动按比例分配新增资源,例如当集群新增节点后,每个队列获得的绝对资源量会同步增加。但这也可能导致业务队列获得超出实际需求的资源量,如参考资料中提到的案例:"当集群中有新的节点加入时,队列资源随着增大,但业务上该队列可能不需要更大资源"(CSDN,2021)。
FairScheduler则采用固定值定义资源配额(如vcores=10,memory-mb=20GB),通过XML配置文件明确指定最大资源量。这种机制能精确控制队列资源上限,避免资源过度分配,但需要人工调整资源配置以适应集群规模变化。腾讯云开发者社区(2021)指出:"FairScheduler的队列资源最大大小是固定可控的",这种特性在需要严格资源隔离的场景中更具优势。
CapacityScheduler采用三级资源分配策略:首先通过深度优先遍历选择资源利用率最低的叶子队列,然后按照FIFO原则选择该队列中最早提交的应用程序,最后为应用分配优先级最高的Container。其默认使用DefaultResourceCalculator仅考虑内存资源,也可配置DominantResourceCalculator实现基于DRF算法的多维度资源调度。
FairScheduler则采用基于缺额(Deficit)的公平调度算法,通过FairShareComparator动态计算作业的资源缺额,优先调度缺额最大的作业。这种算法能实现更细粒度的资源公平分配,如参考资料所述:"公平是通过作业缺额体现的,调度器每次选择缺额最大的job"(CSDN,2018)。当队列配置了最小资源保障(minShare)时,系统会优先满足该保障值再进行公平分配。
CapacityScheduler在Hadoop 3.x后引入多项企业级功能:
FairScheduler则更侧重灵活性:
CapacityScheduler采用层级properties文件配置,队列容量必须满足∑child=100%的硬性约束。这种设计虽然降低了配置灵活性,但能预防资源分配冲突。如开发者反馈:"同一父队列下的同一级别子队列Capacity之和必须为100,比较麻烦"(CSDN,2021)。
FairScheduler使用XML配置格式,允许子队列资源总和超过父队列容量,通过maxResources参数实现软限制。其配置项更丰富,包括:
<queue name="research">
<minResources>10000 mb,10vcores</minResources>
<maxResources>50000 mb,50vcores</maxResources>
<maxRunningApps>20</maxRunningApps>
<schedulingPolicy>fair</schedulingPolicy>
</queue>大规模基准测试显示,CapacityScheduler在超大规模集群中表现更优:
FairScheduler在中小规模集群(<1000节点)中响应更快:
CapacityScheduler的不足包括:
FairScheduler的缺陷主要有:
在超大规模生产环境中,调度器的选择往往与集群管理复杂度直接相关。某互联网公司CDH集群迁移案例显示,当物理节点规模突破千台、计算内存达到150TB+时,Fair Scheduler在动态负载均衡方面展现出独特优势。该集群原先采用CDH默认的Fair Scheduler,在处理突发性分析任务时,能够自动平衡不同业务线的资源占用,确保临时高优先级查询不会阻塞常规ETL流程。但迁移到自建Hadoop3集群时,技术团队最终选择了Capacity Scheduler,主要考量是其与Node Labels机制的深度集成,能够通过标签实现GPU节点与CPU节点的精确隔离。
这种选择反映了两种典型场景:

微软Hydra项目的测试数据揭示了调度器性能的临界点。在超过5万个节点的大型联邦集群中,Capacity Scheduler展现出每秒40k+容器的分配能力,这得益于其全局调度框架(YARN-5139)对锁机制的优化。具体表现为:
相比之下,Fair Scheduler在中等规模集群(200-500节点)的测试中,对短期任务的响应延迟比Capacity Scheduler低15%-20%,这与其基于内存使用比率的调度算法(used_memory/minShare)密切相关。某电商大促期间的监控数据显示,当瞬时提交数百个实时计算任务时,Fair Scheduler能将任务完成时间的标准差控制在Capacity Scheduler的60%以内。
金融行业的一个典型案例展示了队列配置的关键差异。某银行采用Capacity Scheduler时,其风险计算队列(30%资源)与客户画像队列(50%资源)的配置必须严格满足同级队列容量总和为100%的约束。这导致非高峰时段风险计算队列的闲置资源无法被画像队列充分利用,直到通过"弹性队列容量"特性实现跨队列资源共享。
而同一机构在测试环境使用Fair Scheduler时,通过权重配置(weight=2.0)使实时交易分析队列获得双倍于批量处理队列的资源,同时不需要严格的比例限制。这种灵活性使得在突发市场行情下,系统能自动调整资源分配而不需要管理员干预。但值得注意的是,Fair Scheduler的XML配置格式相比Capacity Scheduler的键值对配置更复杂,某次生产事故分析显示,错误的嵌套队列标签导致过20%的资源分配失效。
视频处理公司的A/B测试数据提供了直观对比。当使用Capacity Scheduler时:
切换到Fair Scheduler后:
这种差异本质上源于两者的设计哲学:Capacity Scheduler的"容量保证"特性确保关键业务不受干扰,而Fair Scheduler的"动态权重调整"更适应负载变化。某跨国企业的解决方案是混合部署——在核心数据仓库使用Capacity Scheduler保证日批处理SLA,同时在临时分析集群采用Fair Scheduler提升资源周转率。
Cloudera CDP的演进方向值得关注。其放弃Fair Scheduler转而全面支持Capacity Scheduler的决策基于三点技术考量:
但开源社区仍保留Fair Scheduler的原因在于其独特的"资源借贷"机制。某AI公司的实验显示,当训练任务突发增长时,Fair Scheduler能自动将空闲的推理资源重新分配,而Capacity Scheduler需要预先设置弹性容量参数。这种差异使得Fair Scheduler在算法研发等非标准化场景中仍不可替代。
Q1:CapacityScheduler和FairScheduler在空闲资源分配时的决策逻辑有何本质区别? A1:CapacityScheduler采用三级资源分配策略,优先选择资源占用率最低的叶子队列(通过深度优先遍历),再选择最早提交的应用程序(FIFO原则),最后根据本地性选择Container。而FairScheduler使用FairShareComparator动态计算队列/应用的资源使用比例(used_memory/minShare),优先分配资源给使用率最低的实体。例如,当集群有空闲资源时,CapacityScheduler会严格遵循队列容量限制,而FairScheduler允许临时借用其他队列的闲置资源。
Q2:两者如何实现多租户场景下的资源隔离? A2:CapacityScheduler通过硬性容量限制(如队列A固定分配30%集群资源)实现强隔离,适合生产环境中的SLA保障;FairScheduler则采用弹性权重(weight参数),允许队列按比例动态共享资源,更适合临时性分析任务。例如,在腾讯云实践中,金融客户通常选择CapacityScheduler确保稳定性,而科研团队偏好FairScheduler的灵活性。
Q3:两种调度器分别支持哪些资源比较算法? A3:CapacityScheduler默认使用DefaultResourceCalculator(仅内存),但可配置为DominantResourceCalculator(DRF算法,同时考虑CPU/内存);FairScheduler原生集成DRF,还支持FIFO和FAIR策略混合使用。例如在阿里云案例中,混合负载集群会启用DRF以避免CPU密集型任务垄断资源。
Q4:资源抢占机制的实现有何不同? A4:CapacityScheduler的抢占基于队列容量保障,当某个队列资源使用低于配置值时触发;FairScheduler的抢占则聚焦公平性阈值(通过fairSharePreemptionThreshold参数控制)。实际测试表明,FairScheduler的抢占响应更快(平均2-3秒),但可能引发更多任务重启。
Q5:如何根据业务需求选择调度器? A5:关键考虑三点:
Q6:配置队列层级时有哪些注意事项? A6:CapacityScheduler要求预定义静态队列,修改需重启ResourceManager;FairScheduler支持动态队列创建(通过配置文件热加载)。典型错误案例包括:在CapacityScheduler中未设置子队列容量导致父队列资源浪费,或在FairScheduler中未合理设置minShare导致小作业饿死。
Q7:为什么YARN的事件驱动模型会影响调度器设计? A7:YARN的异步事件处理机制要求调度器实现必须非阻塞。CapacityScheduler采用增量式分配(每次处理一个NodeManager的心跳),而FairScheduler引入连续分配模式(一次心跳分配多个Container)。这在源码层面体现为:FairScheduler的FSAppAttempt类包含更复杂的资源记账逻辑。
Q8:如何解释两个调度器同质化现象? A8:随着Hadoop版本迭代,两者功能逐渐趋同(如都支持层级队列、DRF算法)。但核心差异仍在设计哲学:CapacityScheduler以队列为中心保障稳定性,FairScheduler以应用为中心追求弹性。实际选型时,新版本(Hadoop 3.0+)建议优先测试FairScheduler,因其功能已覆盖CapacityScheduler大部分特性。
[1] : https://cloud.tencent.com/developer/article/1194446
[2] : https://www.cnblogs.com/jpSpaceX/articles/15032880.html
[3] : https://community.transwarp.cn/article/1194
[4] : https://blog.csdn.net/weixin_46376562/article/details/125855125