PULL/PUSH 调度策略

PUSH调度

PUSH调度是由调度器主动分发任务到指定的节点。
依据任务找节点

优点

任务由调度器主动分配,在不考虑节点过高负载的情况下,任务可以被立即分发下去,不会被搁置。

缺点

  • 需要维护节点资源信息(节点心跳+本身维护)
  • 所需环境必须稳定

PULL调度

PULL调度是各节点主动向调度器领取任务执行。
依据节点找任务

优点

  • 简化设计:调度器不需要关心节点的状态等信息,根据节点想要的任务类型找到任务给它即可。
  • 节点负载合理:节点完成任务则询问调度器领取任务,而不是以Heartbeat的方式周期领取任务。这样性能高的领取任务间隔短,负载相对高;性能低的领取任务间隔长,负载相对低,自适应负载均衡。
  • 环境可以动态变化

缺点

  • 任务搁置:当节点数量不多,各节点都有任务,这时任务可能被搁置。
  • 空闲心跳:当节点空闲,调度器没有任务分配时,节点仍需以心跳的方式周期询问是否有任务需要做。

YARN 2.x 的周期PULL调度

在Hadoop YARN中,本质是一种PULL的调度策略:在2.x中,各节点发送Heartbeat,然后调度器对该节点进行分配任务。

调度器先从Heartbeat中接受任务执行情况信息,如果执行完成,完成释放资源等操作。然后根据节点所在地点(数据局部性)、可用资源等信息遍历任务,寻找可以在该节点执行的任务,返回给节点,并完成资源分配。

这是一个PULL的过程,但是Heartbeat是周期性的(3s),不是前面提到完成任务立即报告完成情况,虽然多了些延迟,但是能避免任务被搁置的情况(节点资源不足,肯定被搁置,但是,YARN有预约机制)。

但是,在这2.x的策略下,不能保证任务被最适合的节点执行,因为是根据节点找可执行的任务,只要是可执行的任务就有可能被分配在该节点,这不能保证是对任务的最优分配,于是有了YARN 3.x的Global Schedule。

YARN 3.x 的PULL/PUSH混合调度

在3.x中很关键的是Global Schedule的设计与实现:取消依据节点寻找可执行任务的策略,改用依据应该执行的任务寻找最优执行的节点。并且任务调度与节点心跳异步。

任务调度(PUSH):按照调度策略根据全局资源信息,选择应该执行的任务,然后根据其资源请求信息,对可执行该任务的节点集进行排序,按照排序的结果遍历节点,找到第一个可以分配的节点,然后进行分配。在此处仅是将分配结果保存在某个变量中,等待节点来领取。

领取任务(PULL):节点发送心跳,报告任务完成情况,然后查看是否有对自己的任务分配,有的话,则领取确认。(这一部分不确定

具体细节,如最优节点挂了,迟迟没有心跳的情况,还没有了解

PULL/PUSH调度的应用场景

按任务类型分类

数据密集型应用

数据密集型应用更适用于PUSH调度:PUSH调度能够依据数据局部性,尽可能的让任务在具有数据的节点执行,避免远程读取文件。正符合Global Schedule的思路。

计算密集型应用

计算密集型应用更适用于PULL调度:计算密集型任务,输入数据量小,所需资源量不好衡量,通过PULL调度,能够让调度器不关心节点的负载情况,简化设计。并且,在任务结束后,立即询问调度器(可以与汇报结果结合),能够降低延迟(不需要等待心跳时才汇报信息)。

PULL调度在边缘的设计

在边缘侧,设备变化频繁,更适用于PULL调度。并且人脸识别、语音识别计算量大,属于计算密集型应用。而且,如果设备没有计算能力,必然会产生数据传输,所以不考虑数据局部性。因此,在这里只考虑计算密集型任务,并按任务量分类讨论。

任务稀疏

有任务到了调度器,给网络里所有设备发送一个通知信号,通知有一个任务到达,并说明任务类型。能处理该种任务的设备,发送领取任务的信号,由于任务比较稀疏,可以花一点时间选举出最优节点来执行该任务(目前还不清楚选举算法耗时

这样实施的目的是消除了空闲心跳的弊端,没有空闲心跳,意味着任何设备在任何时候都可以注册为调度器,分发任务。

任务密集

节点空闲则询问调度器领取任务,节点资源利用率高,并且,由于任务密集,所以没有空闲心跳的问题。

容错考虑

如果一个任务长时间没有被执行结束,而节点集群空闲资源较多,可以将同一任务在多个节点同时进行,记录第一个结果即可。