yarn
YARN的基本思想
YARN的基本思想是将资源管理和作业调度/监视功能划分为单独的守护进程。其思想是拥有一个全局ResourceManager (RM)为资源调度以及每个应用程序拥有一个ApplicationMaster (AM)作业调度。应用程序可以是单个作业,也可以是一组作业。
在MR程序运行时,有五个独立的进程:
- YarnRunner: 用于提交作业的客户端程序
- ResourceManager: yarn资源管理器,负责协调集群上计算机资源的分配
- NodeManager: yarn节点管理器,负责启动和监视集群中机器上的计算容器(container)
- Application Master: 负责协调运行MapReduce作业的任务,他和任务都在容器中运行,这些容器由资源管理器分配并由节点管理器进行管理。
- HDFS:用于共享作业所需文件。
上图详解过程如下:
- 初始化job , jobcommiter提交任务
- 申请任务id(资源管理 批不批这个任务)
- 客户端上传资源文件(计算程序,分片数量,所需架包等等)上传到hdfs,供所需要的下载
- 完成上述后,客户端正式向resourcemananger提交作业
- 收到后,找nodemanager 看哪个节点负载不高,通知该nodemanager开启 容器 用来初始化AM
- 初始化AM ,接受每一个任务的回馈,
- 获取分片信息 ,知晓需要多少maptask reduce task
- 向resourcemananger申请资源,resourcemananger返回空闲nodemanager节点信息
- 找到对应nodemanager,申请开辟容器,执行任务
- Yarnchild下载 3 过程中所上传的公共资源
- 跑程序,执行状态向AM汇报,同时1过程会每秒轮寻AM状态,控制台打印日志。运行完会回收RM资源
YARN的三种调度器
Scheduler即调度器,根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。
YARN提供的三种内置调度器:
FIFO Scheduler(FIFO调度器)
FIFO 为 First Input First Output 的缩写,先进先出。FIFO 调度器将应用放在一个队列中,按照先后顺序
运行应用。这种策略较为简单,但不适合共享集群,因为大的应用会占用集群的所有资源,每个应用必须等待直到轮到自己。
优点:简单易懂,不需要任何配置
缺点:不适合共享集群,大的应用会占据集群中的所有资源,所以每个应用都必须等待,直到轮到自己执行。
如下图所示,只有当job1全部执行完毕,才能开始执行job2
Capacity Scheduler(容量调度器)
容量调度器 Capacity Scheduler 允许多个组织共享一个 Hadoop 集群。使用容量调度器时,一个独立的专门队列保证小作业一提交就可以启动。
优点:小任务不会因为前面有大任务在执行,而只能一直等下去
缺点:这种策略是以整个集群利用率为代价的,这意味着与使用FIFO调度器相比,大作业执行的时间要长上一些。
而在Hadoop 3.x版本中,默认的资源调度器是Capacity Scheduler。
如图所示,专门留了一部分资源给小任务(一般百分之80留给大作业,具体可以通过配置参数设置,相当于一直给小作业留了一个百分之20的后门),可以在执行job1的同时,不会阻塞job2的执行,但是因为这部分资源是一直保留给其他任务的,所以就算只有一个任务,也无法为其分配全部资源,只能让这部分保留资源闲置着,有着一定的资源浪费问题。
Fair Scheduler(公平调度器)
公平调度器的目的就是为所有运行的应用公平分配资源。使用公平调度器时,不需要预留一定量的资源,因为调度器会在所有运行的作业之间动态平衡资源,第一个(大)作业启动时,它也是唯一运行的作业,因而获得集群中的所有
资源,当第二个(小)作业启动时,它被分配到集群的一半资源,这样每个作业都能公平共享资源(小作业到来时系统分出50的资源给小作业执行)。
MapReduce
map阶段
map任务数量近似等于数据分块(block默认128m)的数量
大致流程如下
1. 一个mr程序启动的时候,会先启动一个进程Application Master,它的主类是MRAppMaster
2. ApplicationMaster启动之后会根据本次job的描述信息,计算出inputSplit的数据,也就是MapTask的数量
3. ApplicationMaster然后向ResourceManager来申请对应数量的容器Container来执行MapTask进程。
4. MapTask进程启动之后,根据对应的inputSplit来进行数据处理,处理流程如下
1. 利用客户指定的inputformat来获取recordReader按行读取数据,形成kv键值对。
2. 将kv传递给客户定义的Mapper类的map方法,做逻辑运算, map方法的输出kv由outputcontroller写入环形缓冲区(内存区域,可以看作由数组实现)百分之80的环形缓冲区写满后,将数据进行分区,排序(环形缓冲区内快速排序) 。
3. 将合并排序后的数据溢写到磁盘,此时若干的很多小文件已然有序,有序自然用归并排序合并溢写文件。 每一个maptask最终生成一个大的临时文件,最后向ApplicationMaster汇报任务结束,文件存放位置,至此,maptask下班!
环形缓冲区
环形缓冲区实际上是一个字节数组(byte[]),通常被称为Kvbuffer。它不仅用于存储数据,还包含一些索引数据,这些索引数据被存储在Kvmeta中。在Kvbuffer中,数据区域和索引数据区域是相邻且不重叠的,它们之间通过一个分界点来划分。这个分界点不是固定的,每次数据溢出(Spill)到磁盘后,分界点都会更新。
环形缓冲区的设计非常巧妙。在写入数据时,数据是从“赤道”的右边开始写入的(键值对数据Meta),而索引是从“赤道”的左边开始写的(Records<k,v>),这样两者互不干涉。当数据和索引的大小之和达到一个设定的比例时(默认百分之80),会触发溢出操作。在溢出过程中,会对写入的数据进行原地排序(排序只交换索引),并将排序好的数据和索引溢出到磁盘上。然后,在空闲的20%区域中,会重新计算一个新的“赤道”,并继续在新“赤道”的右边写入数据,左边写入索引。如果20%的区域写满但80%的数据还未溢出到磁盘,程序会暂停,等待80%的空间被释放后再继续写入。
reduce阶段
reduce任务数量=生成分区个数=输出文件个数
5. ApplicationMaster监控mapTask进程完成之后,会根据用户指定的参数来启动相应的reduceTask进程,并告知reduceTask需要处理的数据范围与位置
6. ReduceTask启动之后,根据ApplicationMaster告知的待处理的数据位置,从若干的已经存到磁盘的数据中拿到数据(fetch数据),并在本地进行一个归并排序,然后,再按照相同的key的kv为一组,调用客户自定义的reduce方法,并收集输出结果kv,然后按照用户指定的outputFormat将结果存储到外部设备。