Hadoop系列-Yarn

Yarn产生背景

image.png
在Hadoop1.0中, JobTracker负责全局的资源管理和作业调度,存在一些局限:

  • 扩展性差: 资源管理和作业调度功能耦合,很难扩展
  • 可靠性差: 存在单点问题
  • 资源利用率低: 采用了基于槽位的资源分配模型,分为Map/Reduce Slot, 且不允许它们之间共享,无法做到细粒度的资源划分
  • 无法支持其他计算框架

YARN/MRv2 最基本的想法是将原 JobTracker 主要的资源管理和 Job 调度/监视功能分开。ResourceManager负责集群所有节点的资源统一管理调度,ApplicationMaster管理在YARN内运行的每个应用程序实例,负责协调来自ResourceManager的资源,并通过NodeManager监视容器的执行和资源使用

Yarn基本架构

image.png

  • Resource Manager: master角色, 负责整个系统的资源管理和分配。 它主要由两个组件构成: 调度器( Scheduler) 和应用程序管理器( Applications Manager, ASM)

  • Application Master:用户提交的每个应用程序均包含一个 AM, 主要功能包括:

    1. 与RM调度器协商获取资源
    2. 与NM通信启动/停止任务
    3. 监控所有任务运行状态, 并在任务运行失败时重新为任务申请资源以重启任务
  • Node Manager:slave角色,是每个节点上的资源和任务管理器。一方面, 它会定时地向 RM 汇报本节点上的资源使用情况和各个 Container 的运行状态;另一方面,它接收并处理来自 AM 的 Container 启动/停止等各种请求

  • Container: Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当AM向RM申请资源时,RM为AM返回的资源便是用Container表示的

Yarn工作流程

Yarn工作流程.png

  1. 用户向 YARN 中提交应用程序, 其中包括AM程序、启动AM的命令、用户程序等。

  2. RM 为该应用程序分配第一个 Container,并与对应的 NM 通信,要求它在这个 Container 中启动应用程序的 AM

  3. AM 首先向 RM 注册,这样用户可以直接通过 RM 查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束, 即重复步骤 4~7。

  4. AM 采用轮询的方式通过 RPC 协议向 RM 申请和领取资源。

  5. 一旦 AM 申请到资源后,便与对应的 NM 通信,要求它启动任务。

  6. NM 为任务设置好运行环境(包括环境变量、JAR 包、二进制程序等)后, 将任务启动命令写到一个脚本中, 并通过运行该脚本启动任务。

  7. 各个任务通过某个 RPC 协议向 AM 汇报自己的状态和进度, 以让 AM 随时掌握各个任务的运行状态, 从而可以在任务失败时重新启动任务。

  8. 应用程序运行完成后, ApplicationMaster 向 ResourceManager 注销并关闭自己

三种调度器

  • FIFO调度器: 先进先出队列,按工作队列中作业到达顺序执行调度,容易实现,但无法考虑到特殊作业的优先级

  • 公平调度器FairScheduler:

    1. 创建一组工作池,默认情况下每个池分配相等的集群共享资源,但可以配置,需要系统进行加载后才能生效
    2. 调度器会追踪作业的计算时间,通过与理想时间的差距分析,然后保证差距最大的任务在后面优先执行
    3. 一个用户对应一个工作池,类似于一个资源调度基本单位,无论这个用户提交多少个作业,它与其他用户的资源都是公平相等的,与作业无关
  • Capacity容量调度器:

    1. 类似公平调度器,但也有一些区别,通过分配专门的队列可以实现多个组织共享集群资源
    2. 可自定义队列的资源配置,动态更新配置文件, 队列内部资源又可以划分给同一组织下的多个成员共享
    3. 可以调整队列中作业的优先级。一般来说,具有高优先级的作业访问资源比低优先级作业更快

Hadoop资源调度会不会产生死锁现象?

死锁的四个条件: 互斥、请求与保持、不可剥夺、循环等待,Hadoop资源调度允许抢占, 资源抢占是通过杀死正在使用的资源Container实现的,这就使得请求与保持不可剥夺两个条件无法满足,从而也就不会产生死锁现象了

补充:
某些Container可能已经处于运行状态了,直接杀死Container剥夺资源会导致已经完成的计算资源白白浪费,因此Yarn会优先选择优先级低的Container作为资源抢占对象,且不会立刻杀死Container: ResourManager将待杀死的Container列表发送给对应的ApplicationMaster, 以期望它采取一定的机制自行释放这些Container占用的资源,比如先进行一些计算状态的保存,然后再杀死Container,如果一段时间后还没有啥似的话,ResourceManager再强制杀死这些Container

分布式调度

  • 集中式单体调度, 所有资源的使用和任务的执行状态都由一个中央调度器来控制,并发小,可扩展性差且存在单点问题,代表为Hadoopv1 JobTracker架构

  • 双层调度: 加入了一个框架调度器,各个框架在接收到资源时可以在内部使用自身的调度策略进行更细粒度的资源分配,代表为Golang的Goroutine协程调度器, Mesos

  • 共享状态调度: 每个框架都存有一份私有并不断更新的副本可以看到全局的资源使用情况,根据需要获取资源,资源竞争通过事务控制保证原子性,且采用乐观锁机制提高了并发,代表为Google的Omega

参考