Lazy loaded image
🐘Hadoop基本概念(三):YARN
字数 20805阅读时长 53 分钟
2025-9-2
2025-10-28
type
status
date
slug
summary
tags
category
icon
password

一、YARN背景知识

1.YARN发展历史

YARN是Hadoop 2引入的通用资源管理和任务调度平台,支持运行MapReduce、Tez、Spark等多种计算框架。只要计算框架实现了YARN定义的接口,就可以在这套通用平台上运行。
Hadoop 1.0由HDFS和MapReduce V1组成,YARN出现前由MapReduce V1负责资源管理和任务调度。MapReduce V1主要由JobTracker和TaskTracker两部分构成。
MapReduce V1有以下缺点:
  1. 扩展性差:JobTracker同时负责资源管理和任务调度,且只有一个节点,成为系统性能的瓶颈,限制了Hadoop平台的扩展性。
  1. 可靠性低:JobTracker存在单点故障问题。
  1. 资源利用率低:MapReduce V1采用基于槽位的资源分配模型,这种粗粒度的资源划分单位存在明显限制。
  • 一是分配给作业的槽位通常无法被充分利用。
  • 二是MapReduce任务的Map阶段和Reduce阶段被划分为固定槽位且不可共用,导致某种类型的槽位资源紧张而另一种类型空闲,降低了整体资源利用率。
  1. 不支持多种计算框架:MapReduce V1这种资源管理和任务调度方式只适合MapReduce这种计算框架,而MapReduce这种离线计算框架很多时候不能满足应用需求。数据可共享共享集群模式可以让多种框架共享数据和硬件资源,减少数据移动带来的成本。引入YARN之后,带来了如下特性:支持多种计算框架YARN是通用的资源管理和任务调度平台,只要实现了YARN的接口的计算框架都可以运行在YARN上。资源利用率高多种计算框架可以共用一套集群资源,让资源充分利用起来,提高了利用率。运维成本低避免一个框架一个集群的模式,YARN降低了集群的运维成本。
引入YARN之后,带来了如下特性:
  1. 支持多种计算框架:YARN是通用的资源管理和任务调度平台,只要实现了YARN的接口的计算框架都可以运行在YARN上。
  1. 资源利用率高:多种计算框架可以共用一套集群资源,让资源充分利用起来,提高了整体利用率。
  1. 运维成本低:避免"一个框架一个集群"的模式,YARN显著降低了集群的运维成本。
  1. 数据可共享:让多种框架共享数据和硬件资源,减少了数据移动带来的成本。。
Hadoop2.0中将资源管理任务分给了YARN的ResourceManage,将任务调度分给了YARN的ApplicationMaster。
1.3 yarn 集群的架构和工作原理
YARN的基本设计思想是将MapReduce V1中的JobTracker拆分为两个独立的服务:ResourceManager和ApplicationMaster。ResourceManager负责整个系统的资源管理和分配,ApplicationMaster负责单个应用程序的的管理。
notion image
1ResourceManager
RM是一个全局的资源管理器,负责整个系统的资源管理和分配,它主要由两个部分组成:调度器(Scheduler)和应用程序管理器(Application Manager)。
调度器根据容量、队列等限制条件,将系统中的资源分配给正在运行的应用程序,在保证容量、公平性和服务等级的前提下,优化集群资源利用率,让所有的资源都被充分利用 。
应用程序管理器负责管理整个系统中的所有的应用程序,包括应用程序的提交、与调度器协商资源以启动ApplicationMaster、监控ApplicationMaster运行状态并在失败时重启它。
2ApplicationMaster
用户提交的一个应用程序会对应于一个ApplicationMaster,它的主要功能有:
●与RM调度器协商以获得资源,资源以Container表示。
●将得到的任务进一步分配给内部的任务。
●与NM通信以启动/停止任务。
●监控所有的内部任务状态,并在任务运行失败的时候重新为任务申请资源以重启任务。
3nodeManager
NodeManager是每个节点上的资源和任务管理器,一方面,它会定期地向RM汇报本节点上的资源使用情况和各个Container的运行状态;另一方面,他接收并处理来自AM的Container启动和停止请求。
4container
Container是YARN中的资源抽象,封装了各种资源。一个应用程序会分配一个Container,这个应用程序只能使用这个Container中描述的资源。
不同于MapReduceV1中槽位slot的资源封装,Container是一个动态资源的划分单位,更能充分利用资源。
1.4 yarn 的任务提交流程
notion image
当jobclient向YARN提交一个应用程序后,YARN将分两个阶段运行这个应用程序:一是启动ApplicationMaster;第二个阶段是由ApplicationMaster创建应用程序,为它申请资源,监控运行直到结束。
具体步骤如下:
1用户向YARN提交一个应用程序,并指定ApplicationMaster程序、启动ApplicationMaster的命令、用户程序。
2RM为这个应用程序分配第一个Container,并与之对应的NM通讯,要求它在这个Container中启动应用程序ApplicationMaster。
3ApplicationMaster向RM注册,然后拆分为内部各个子任务,为各个内部任务申请资源,并监控这些任务的运行,直到结束。
4AM采用轮询的方式向RM申请和领取资源。
5RM为AM分配资源,以Container形式返回
6AM申请到资源后,便与之对应的NM通讯,要求NM启动任务。
7NodeManager为任务设置好运行环境,将任务启动命令写到一个脚本中,并通过运行这个脚本启动任务
8各个任务向AM汇报自己的状态和进度,以便当任务失败时可以重启任务。
9应用程序完成后,ApplicationMaster向ResourceManager注销并关闭自己
2. RM和NM的功能介绍 2.1 resourceManager基本介绍
ResourceManager负责集群中所有资源的统一管理和分配,它接收来自各个NodeManager的资源汇报信息,并把这些信息按照一定的策略分配给各个ApplicationMaster。
2.1.1 RM的职能
1与客户端交互,处理客户端的请求。
2启动和管理AM,并在它运行失败时候重新启动它。
3管理NM,接收来自于NM的资源汇报信息,并向NM下达管理指令。
4资源管理和调度,接收来自于AM的资源请求,并为它分配资源。
2.1.2 RM 的内部结构
notion image
用户交互模块:
1clientRMService : 为普通用户服务,处理请求,如:提交应用程序、终止程序、获取程序状态
2adminService : 给管理员提供的服务。普通用户交互模块是ClientRMService,管理员交互模块是AdminService,之所以要将两个模块分开,用不同的通信通道发送给ResourceManager,是因为要避免普通用户的请求过多导致管理员请求被阻塞
3WebApp : 更友好的展示集群资源和程序运行状态
NM管理模块:
1NMLivelinessMonitor : 监控NM是否活着,如果指定时间内未收到心跳,就从集群中移除。RM会通过心跳告诉AM某个NM上的Container失效,如果Am判断需要重新执行,则AM重新向RM申请资源。
2NodesListManager : 维护inlude(正常)和exlude(异常)的NM节点列表。默认情况下,两个列表都为空,可以由管理员添加节点。exlude列表里的NM不允许与RM进行通信。
3ResourceTrackerService : 处理来自NM的请求,包括注册和心跳。注册是NM启动时的操作,包括节点ID和可用资源上线等。心跳包括各个Container运行状态,运行Application列表、节点健康状态
AM管理模块:
1AMLivelinessMonitor : 监控AM是否还活着,如果指定时间内没有接受到心跳,则将正在运行的Container置为失败状态,而AM会被重新分配到另一个节点上
2ApplicationMasterLauncher: 要求某一个NM启动ApplicationMaster,它处理创建AM的请求和kill AM的请求
3ApplicationMasterService : 处理来自AM的请求,包括注册、心跳、清理。注册是在AM启动时发送给ApplicationMasterService的;心跳是周期性的,包括请求资源的类型、待释放的Container列表;清理是程序结束后发送给RM,以回收资源清理内存空间;
Application管理模块:
1ApplicationACLLsManager : 管理应用程序的访问权限,分为查看权限和修改权限。
2RMAppManager : 管理应用程序的启动和关闭
3ContainerAllocationExpirer : RM分配Container给AM后,不允许AM长时间不对Container使用,因为会降低集群的利用率,如果超时(时间可以设置)还没有在NM上启动Container,RM就强制回收Container。
状态机管理模块:
1RMApp : RMApp维护一个应用程序的的整个运行周期,一个应用程序可能有多个实例,RMApp维护的是所有实例的
2RMAppAttempt : RMAppAttempt维护一个应用程序实例的一次尝试的整个生命周期
3RMContainer : RMContainer维护一个Container的整个运行周期(可能和任务的周期不一致)
4RMNode : RMNode维护一个NodeManager的生命周期,包括启动到运行结束的整个过程。
安全模块:
●RM自带了全面的权限管理机制。主要由ClientToAMSecretManager、ContainerTokenSecretManager、ApplicationTokenSecretManager等模块组成。
资源分配模块:
●ResourceScheduler:ResourceScheduler是资源调度器,他按照一定的约束条件将资源分配给各个应用程序。RM自带了一个批处理资源调度器(FIFO)和两个多用户调度器Fair Scheduler 和Capacity Scheduler
2.1.3 启动ApplicationMaster
notion image
1客户端提交一个任务给RM,ClientRMService负责处理客户端请求
2ClentRMService通知RMAppManager。
3RMAppManager为应用程序创建一个RMApp对象来维护任务的状态。
4RMApp启动任务,创建RMAppAttempt对象。
5RMAppAttempt进行一些初始化工作,然后通知ResourceScheduler申请资源。
6ResourceScheduler为任务分配资源后,创建一个RMContainer维护Container状态
7并通知RMAppAttempt,已经分配资源。
8RMAppAttempt通知ApplicationMasterLauncher在资源上启动AM。
9在NodeManager的已分配资源上启动AM
10AM启动后向ApplicationMasterService注册。
2.1.4 申请和分配container
AM向RM请求资源和RM为AM分配资源是两个阶段的循环过程:
●阶段一:AM请求资源请求并领取资源的过程,这个过程是AM发送请求、RM记录请求。
●阶段二:NM向RM汇报各个Container运行状态,如果RM发现它上面有空闲的资源就分配给等待的AM。
具体过程如下:
阶段一:
1AM通过RPC函数向RM发送资源需求信息,包括新的资源需求描述、待释放的Container列表、请求加入黑名单的节点列表、请求移除黑名单的节点列表等
2RM的ApplicationMasterService负责处理AM的请求。一旦收到请求,就通知RMAppAttempt,更新应用程序执行进度,在AMLivenessMonitor中记录更新时间。
3ApplicationMasterService调用ResourceScheduler,将AM的资源需求汇报给ResourceScheduler。
4ResouceScheduler首先读取待释放的Container列表,通知RMContainer更改状态,杀死要释放的Container,然后将新的资源需求记录,如果资源足够就记录已经分配好资源。
阶段二:
1NM通过RPC向RM汇报各自的各个Container的运行情况
2RM的ResourceTrackerService负责处理来自NM的汇报,收到汇报后,就通知RMNode更改Container状态,并通知ResourceScheduler。
3ResourceScheduler收到通知后,如果有可分配的空闲资源,就将资源分配给等待资源的AM,等待AM下次心跳将资源领取走。
notion image
2.1.5 杀死 application
杀死Application流程:
Kill Job通常是客户端发起的,RM的ClientRMService负责处理请求,接收到请求后,先检查权限,确保用户有权限Kill Job,然后通知维护这个Application的RMApp对象,根据Application当前状态调用相应的函数来处理。
这个时候分为两种情况:Application没有在运行、Application正在运行。
1Application没有在运行
向已经运行过的NodeManger节点对应的状态维护对象RMNode发送通知,进行清理;向RMAppManager发送通知,将Application设置为已完成状态。
2Application正在运行
如果正在运行,也首先像情况一处理一遍,回收运行过的NodeManager资源,将Application设置为已完成。另外RMApp还要通知维护任务状态的RMAppAttempt对象,将已经申请和占用的资源回收,但是真正的回收是由资源调度器ResourceScheduler异步完成的。
异步完成的步骤是先由ApplicationMasterLauncher杀死AM,并回收它占用的资源,再由各个已经启动的RMContainer杀死Container并回收资源。
2.1.6 Container超时
YARN里有两种Container:运行AM的Container和运行普通任务的Container。
1RM为要启动的AM分配Container后,会监控Container的状态,如果指定时间内AM还没有在Container上启动的话,Container就会被回收,AM Container超时会导致Application执行失败。
2普通Container超时会进行资源回收,但是YARN不会自动在其他资源上重试,而是通知AM,由AM决定是否重试。
2.1.7 安全管理
Hadoop的安全管理是为了更好地让多用户在共享Hadoop集群环境下安全高效地使用集群资源。系统安全机制由认证和授权两大部分构成,Hadoop2.0中的认证机制采用Kerberos和Token两种方案,而授权则是通过引入访问控制表(Access Control List,ACL)实现的。
1术语
Kerberos是一种基于第三方服务的认证协议,非常安全。特点是用户只需要输入一次身份验证信息就可以凭借此验证获得的票据访问多个服务。
Token是一种基于共享密钥的双方身份认证机制。
Principal是指集群中被认证或授权的主体,主要包括用户、Hadoop服务、Container、Application、Localizer、Shuffle Data等。
2Hadoop认证机制
Hadoop同时采用了Kerberos和Token两种技术,服务和服务之间的认证采用了Kerberos,用户和NameNode及用户和ResourceManager首次通讯也采用Kerberos认证,用户和服务之间一旦建立连接后,用户就可以从服务端获取一个Token,之后就可以使用Token认证通讯了。因为Token认证要比Kerberos要高效。
Hadoop里Kerberos认证默认是关闭的,可以通过参数hadoop.security.authentication设置为kerberos,这个配置模式是simple。
3Hadoop授权机制
Hadoop授权是通过访问控制列表(ACL)实现的,Hadoop的访问控制机制与UNIX的POSIX风格的访问控制机制是一致的,将权限授予对象分为:用户、同组用户、其他用户。默认情况下,Hadoop公用UNIX/Linux下的用户和用户组。
●队列访问控制列表
●应用程序访问控制列表
●服务访问控制列表
2.2 nodeManager功能介绍
NM是单个节点上的代理,功能包括与ResourceManager保持通讯、管理Container的生命周期、监控Container的资源使用、追踪节点健康状态、管理日志。
2.2.1 基本内部构造
notion image
模块
说明
NodeStatusUpdater
NodeStatusUpdater是NM和RM通讯的唯一通道。NM启动时,该组件负责向RM注册、汇报节点总的可用资源。该组件周期性地汇报各个Container的状态,接收RM返回的待清理的Container列表等
ContainerManager
ContainerManager是NM最核心的模块。
RPC Server
是AM和NM通讯的唯一通道,接收AM请求,启动或者停止Container
ResourceLocalizationService
负责Container所需资源的本地化,下载文件资源,尽量分摊到各个磁盘。
ContainersLauncher
维护一个线程池并行操作Container。
AuxServices
NM附属服务。
ContainersMonitor
ContainersMonitor负责监控Container的资源使用量。
LogHandler
用户可以通过LogHandler控制Container日志保存方式。
ContainerEventDispatcher
Container事件调度器,负责将ContainerEvent类型的事件调度给对应的Container的状态机
ApplicationEventDispatcher
Application事件调度器,负责将ApplicationEvent类型的事件调度给对应
ContainerExecutor
ContainerExecutor可与底层操作系统交互,安全存放Container需要的文件和目录,启动和清除Container对应的进程。
NodeHealthCheckerServiceNodeHealthCheckerService
通过周期性运行一个脚本和写磁盘检测节点的健康状况,并通知RM。NodeHealthScriptRunner:运行脚本检测LocalDirsHandlerService:写磁盘文件检测
DeletionService
NM将文件删除功能化,DeletionService异步删除文件,避免同步删除文件带来的性能开销。
Security
安全模块分为两部分:ApplicationACLManager确保访问NM的用户是合法的。ContainerTokenSecreManager确保用户请求的资源被RM授权过
WebServer
Web UI向用户展示
2.2.2 状态机管理
NodeManager维护着三类状态机,分别是Application、Container、LocalizedResource。
1Application状态机
RM上有一个整个集群上Application信息列表,而一个NM上也有一个处在它自己节点的Application的信息列表,NodeManager上的Application状态机维护着NodeManager上Application的状态。
这有利于对一个NM节点上的同一个Application所有的Container进行统一管理。
2Container状态机Container状态机维护NodeManager上所有Container的生命周期。
3LocalizedResource状态机LocalizedResource状态是NodeManager上用于维护一个资源生命周期的数据结构。资源包括文件、JAR包等。
2.2.3 container生命周期的管理
NodeManager中的ContainerManager负责接收AM发来的请求以启动Container,Container的启动过程分三个阶段:资源本地化、启动并运行Container、资源清理。
1资源本地化
资源本地化主要是进行分布是缓存工作,分为应用程序初始化和Container本地化。
2运行Container
Container运行是由ContainerLauncher服务完成启动后,调用ContainerExecutor来进行的。主要流程为:将待运行的Container所需要的环境变量和运行命令写到Shell脚本launch_container.sh中,并将启动该脚本的命令写入default_container_executor.sh中,然后通过运行该脚本启动container。
3资源清理
container清理是资源本地化的逆过程,是指当container运行完成后,NodeManager来回收资源。
3. yarn的applicationMaster介绍
ApplicationMaster实际上是特定计算框架的一个实例,每种计算框架都有自己独特的ApplicationMaster,负责与ResourceManager协商资源,并和NodeManager协同来执行和监控Container。MapReduce只是可以运行在YARN上一种计算框架。
3.1 applicationMaster的职能
Application启动后,将负责以下任务:
1初始化向ResourceManager报告自己的活跃信息的进程 (注册)
2计算应用程序的的资源需求。
3将需求转换为YARN调度器可以理解的ResourceRequest。
4与调度器协商申请资源
5与NodeManager协同合作使用分配的Container。
6跟踪正在运行的Container状态,监控它的运行。
7对Container或者节点失败的情况进行处理,在必要的情况下重新申请资源。
3.2 报告活跃
1注册
ApplicationMaster执行的第一个操作就是向ResourceManager注册,注册时AM告诉RM它的IPC的地址和网页的URL。
IPC地址是面向客户端的服务地址;网页URL是AM的一个Web服务的地址,客户端可以通过Http获取应用程序的状态和信息。
注册后,RM返回AM可以使用的信息,包括:YARN接受的资源的大小范围、应用程序的ACL信息。
2心跳
注册成功后,AM需要周期性地发送心跳到RM确认他还活着。参数yarn.am.liveness-monitor.expiry配置AM心跳最大周期,如果RM发现超过这个时间还没有收到AM的心跳,那么就判断AM已经死掉。
3.3 资源需求
AM所需要的资源分为静态资源和动态资源。
1静态资源
在任务提交时就能确定,并且在AM运行时不再变化的资源是静态资源,比如MapReduce程序中的Map的数量。
2动态资源
AM在运行时确定要请求数量的资源是动态资源。
3.4 调度任务
当AM的资源请求数量达到一定数量或者到了心跳时,AM才会发送心跳到RM,请求资源,心跳是以ResourceRequest形式发送的,包括的信息有:resourceAsks、ContainerID、containersToBeReleased。
RM响应的信息包括:新分配的Container列表、已经完成了的Container状态、集群可用的资源上限。
3.5 启动container
1AM从RM那里得到了Container后就可以启动Container了。
2AM首先构造ContainerLaunchContext对象,包括分配资源的大小、安全令牌、启动Container执行的命令、进程环境、必要的文件等
3AM与NM通讯,发送StartContainerRequest请求,逐一或者批量启动Container。
4NM通过StartContainerResponse回应请求,包括:成功启动的Container列表、失败的Container信信息等。
5整个过程中,AM没有跟RM进行通信。
6AM也可以发送StopContainerRequest请求来停止Container。
3.6 完成的container
当Container执行结束时,由RM通知AM Container的状态,AM解释Container状态并决定如何继续操作。所以YARN平台只是负责为计算框架提供Container信息。
3.7 AM的失败和恢复
当AM失效后,YARN只负责重新启动一个AM,任务恢复到失效前的状态是由AM自己完成的。AM为了能实现恢复任务的目标,可以采用以下方案:将任务的状态持久化到外部存储中。比如:MapReduce框架的ApplicationMaster会将已完成的任务持久化,失效后的恢复时可以将已完成的任务恢复,重新运行未完成的任务。
3.8 applicationMaster启动过程
notion image
4. yarn的资源调度
1资源调度器的职能
资源调度器是YARN最核心的组件之一,是一个插拔式的服务组件,负责整个集群资源的管理和分配。YARN提供了三种可用的资源调度器:FIFO、Capacity Scheduler、Fair Scheduler。
2资源调度器的分类
不同的任务类型对资源有着不同的负责质量要求,有的任务对时间要求不是很高(如Hive),有的任务要求及时返还结果(如HBase),有的任务是CPU密集型的,有的是I/O密集型的,所以简单的一种调度器并不能完全符合所有的任务类型。
有两种调度器的设计思路:
一是在一个物理Hadoop集群上虚拟多个Hadoop集群,这些集群各自有自己全套的Hadoop服务,典型的代表是HOD(Hadoop On Demand)调度器,Hadoop2.0中已经过时。
另一种是扩展YARN调度器。典型的是Capacity Scheduler、Fair Scheduler。
3基本架构
插拔式组件
YARN里的资源调度器是可插拔的,ResourceManager在初始化时根据配置创建一个调度器,可以通过参数yarn.resourcemanager.scheduler.class参数来设置调度器的主类是哪个,默认是CapacityScheduler,配置值为:org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler。
所有的资源调度器都要实现接口org.apache.hadoop.yarn.server.resourcemanager.scheduler.ResourceScheduler。
事件处理器
YARN的资源管理器实际上是一个事件处理器,它处理6个SchedulerEventType类型的事件。
事件说明:
●Node_Removed 集群中移除一个计算节点,资源调度器需要收到该事件后从可分配的资源总量中移除相应的资源量。
●Node_Added 集群增加一个节点
●Application_added RM收到一个新的Application。
●Application_Remove 表示一个Application运行结束
●Container_expired 当一个Container分配给AM后,如果在一段时间内AM没有启动Container,就触发这个事件。调度器会对该Container进行回收。
●Node_Update RM收到NM的心跳后,就会触发Node_Update事件。
4.1 资源调度三种模型介绍
究竟使用哪种调度模型,取决于这个配置项,apache版本的hadoop默认使用的是capacity scheduler调度方式。CDH版本的默认使用的是fair scheduler调度方式 : yarn-site.xml
1双层资源调度模型
YARN使用了双层资源调度模型。
第一层:ResourceManager中的调度器将资源分配给各个ApplicationMaster。这一层调度由YARN的资源调度器来实现。
第二层:ApplicationMaster再进一步将资源分配给它内部的各个任务。这一层的调度由用户程序这个计算框架来实现。
YARN的资源分配过程是异步的,YARN的调度器分配给AM资源后,先将资源存入一个缓冲区内,当AM下次心跳时来领取资源。
资源分配过程如下7个步骤:
●步骤1:NodeManager通过周期性的心跳汇报节点信息 : 告诉resourceManager当前剩余的资源信息
●步骤2:RM为NM返回一个应答,包括要释放的Container列表。
●步骤3:RM收到NM汇报的信息后,会出发资源调度器的Node_Update事件。
●步骤4:资源调度器收到Node_Update事件后,会按照一定的策略将该节点上资源分配给各个应用程序,并将分配结果存入一个内存数据结构中。
●步骤5:应用程序的ApplicationMaster周期性地向RM发送心跳,以领取最新分配的Container。
●步骤6:RM收到AM的心跳后,将分配给它的Container以心跳应答的方式返回给ApplicationMaster
●步骤7:AM收到新分配的Container后,会将这些Container进一步分配给他的内部子任务。
2资源保证机制
YARN采用增量资源分配机制来保证资源的分配。
增量资源分配机制是指当YARN暂时不能满足应用程序的资源要求时,将现有的一个节点上的资源预留,等到这个节点上累计释放的资源满足了要求,再分配给ApplicationMaster。
这种增量资源分配机制虽然会造成资源的浪费,但是能保证AM肯定会得到资源,不会被饿死。
3资源分配算法
YARN的资源调度器采用了主资源公平调度算法(DRF)来支持多维度资源调度。
4资源抢占模型
资源调度器中,每个队列可以设置一个最小资源量和最大资源量。为了提高集群使用效率,资源调度器会将负载较轻的队列资源分配给负载较重的队列使用,当负载较轻的队列突然接到了新的任务时,调度器才会将本属于该队列的资源分配给它,但是此时资源有可能正被其他队列使用,因此调度器必须等待其他队列释放资源,如果一段时间后发现资源还未得到释放,则进行资源抢占。
关于资源抢占的实现,涉及到一下两个问题:
●如何决定是否抢占某个队列的资源
●如何使得资源抢占代价最小
资源抢占是通过杀死正在使用的Container实现的,由于Container已经处于运行状态,直接杀死Container会造成已经完成的计算白白浪费,为了尽可能地避免资源浪费,YARN优先选择优先级低的Container做为资源抢占的对象,并且不会立刻杀死Container,而是将释放资源的任务留给ApplicationMaster中的应用程序,以期望他能采取一定的措施来执行释放这些Container,比如保存一些状态后退出,如果一段时间后,ApplicationMaster仍未主动杀死Container,则RM再强制杀死这些Container。
4.1.1 层级队列管理机制FIFO调度策略
notion image
Hadoop1.0中使用了平级队列的组织方式,而后来采用了层级队列的组织方式。
层级队列的特点:
●子队列
队列可以嵌套,每个队列都可以包含子队列;用户只能将应用程序提交到叶子队列中。
●最小容量
每个子队列均有一个最小容量比属性,表示可以使用的父队列容量的百分比。
调度器总是优先选择当前资源使用率最低的队列,并为之分配资源。
指定了最小容量,但是不会保证会保持最小容量,同样会被分配给其他队列。
●最大容量
队列指定了最大容量,任何时候队列使用的资源都不会超过最大容量。
默认情况下队列的最大容量是无限大。
●用户权限管理
管理员可以配置每个叶子节点队列对应的操作系统的用户和用户组。
●系统资源管理
管理员设置了每个队列的容量,每个用户可以用资源的量,调度器根据这些配置来进行资源调度
队列命名规则:
为了防止队列名称的冲突和便于识别队列,YARN采用了自顶向下的路径命名规则,父队列和子队列名称采用.拼接。
4.1.2 Capacity Scheduler
notion image
notion image
Capacity Scheduler是Yahoo!开发的多用户调度器。主要有以下几个特点:
●容量保证
管理员可以为队列设置最低保证和资源使用上限,同一个队列里的应用程序可以共享使用队列资源。
●灵活性:
一个队列里的资源有剩余,可以暂时共享给其他队列,一旦该队列有的新的任务,其他队列会归还资源,这样尽量地提高了集群的利用率。
●多重租赁
支持多用户共享集群和多应用程序同时运行
●安全保证
每个队列有严格的ACL列表,限制了用户的权限
●动态更新配置文件
管理员对参数的配置是动态的。
配置方案:
Capacity Scheduler的所有配置都在capactiy-scheduler.xml里,管理员修改后,要通过命令来刷写队列:yarn mradmin –refreshQueues
Capacity Scheduler不允许管理员动态地减少队列数目,且更新的配置参数值应该是合法值。
以下以队列tongyong为例来说明参数配置:
【资源分配相关参数】
【限制应用程序数目相关参数】
【队列的访问和权限控制参数】
4.1.3 Fair Scheduler
notion image
notion image
基本特点:
1资源公平共享
默认是Fair策略分配资源,Fair 策略是一种基于最大最小公平算法实现的,所有应用程序平分资源。
2支持资源抢占
某个队列中有剩余资源时,调度器会将这些资源共享给其他队列,当该队列有了新的应用程序提交过来后,调度器会回收资源,调度器采用先等待再强制回收的策略。
3负载均衡
Fair Scheduler提供了一个基于任务数目的负载均衡机制,尽可能将系统中的任务均匀分布到各个节点上。
4调度策略配置灵活
可以每个队列选用不同的调度策略:FIFO、Fair、DRF
5提高小应用程序的响应时间
小作业也可以分配大资源,可以快速地运行完成
5. yarn的多租户配置实现资源隔离
资源隔离目前有2种,静态隔离和动态隔离。
静态隔离:
所谓静态隔离是以服务隔离,是通过cgroups(LINUX control groups) 功能来支持的。比如HADOOP服务包含HDFS, HBASE, YARN等等,那么我们固定的设置比例,HDFS:20%, HBASE:40%, YARN:40%, 系统会帮我们根据整个集群的CPU,内存,IO数量来分割资源,先提一下,IO是无法分割的,所以只能说当遇到IO问题时根据比例由谁先拿到资源,CPU和内存是预先分配好的。
上面这种按照比例固定分割就是静态分割了,仔细想想,这种做法弊端太多,假设我按照一定的比例预先分割好了,但是如果我晚上主要跑mapreduce, 白天主要是HBASE工作,这种情况怎么办?静态分割无法很好的支持,缺陷太大,这种模型可能不太合适。
动态隔离:
动态隔离主要是针对 YARN, 所谓动态只是相对静态来说,其实也不是动态。先说YARN, 在HADOOP整个环境,主要服务有哪些?mapreduce(这里再提一下,mapreduce是应用,YARN是框架,搞清楚这个概念),HBASE, HIVE,SPARK,HDFS,Flink, 实际上主要的大概这些,很多人估计会表示不赞同,oozie, ES, storm , kylin等等这些和YARN离的太远了,不依赖YARN的资源服务,而且这些服务都是单独部署就OK,关联性不大。所以主要和YARN有关也就是HIVE, SPARK,Mapreduce,Flink。这几个服务也正式目前用的最多的(HBASE用的也很多,但是和YARN没啥关系)。
根据上面的描述,大家应该能理解为什么所谓的动态隔离主要是针对YARN。好了,既然YARN占的比重这么多,那么如果能很好的对YARN进行资源隔离,那也是不错的。如果我有3个部分都需要使用HADOOP,那么我希望能根据不同部门设置资源的优先级别,实际上也是根据比例来设置,建立3个queue name, 开发部们30%,数据分析部分50%,运营部门20%。
设置了比例之后,再提交JOB的时候设置mapreduce.queue.name,那么JOB就会进入指定的队列里面。非常可惜的是,如果你指定了一个不存在的队列,JOB仍然可以执行,这个是目前无解的,默认提交JOB到YARN的时候,规则是root.users.username , 队列不存在,会自动以这种格式生成队列名称。队列设置好之后,再通过ACL来控制谁能提交或者KIll job。
从上面2种资源隔离来看,没有哪一种做的很好,如果非要选一种,建议选取后者,隔离YARN资源, 第一种固定分割服务的方式实在支持不了现在的业务。
需求:现在一个集群当中,可能有多个用户都需要使用,例如开发人员需要提交任务,测试人员需要提交任务,以及其他部门工作同事也需要提交任务到集群上面去,对于我们多个用户同时提交任务,我们可以通过配置yarn的多用户资源隔离来进行实现
1node01编辑yarn-site.xml
1node01添加fair-scheduler.xml配置文件
3将修改后的配置文件拷贝到其他机器上
4重启yarn集群
5创建普通用户hadoop
6修改文件夹权限
node01执行以下命令,修改hdfs上面tmp文件夹的权限,不然普通用户执行任务的时候会抛出权限不足的异常
7使用hadoop用户提交mr任务
node01执行以下命令,切换到普通用户hadoop,然后使用hadoop来提交mr的任务
四、Hadoop 3.x 版本的新特性 1. Apache Hadoop 3.0.0
Apache Hadoop 3.0.0在以前的主要发行版本(hadoop-2.x)上进行了许多重大改进。
1. 最低要求的Java版本从Java 7增加到Java 8
现在,已针对Java 8的运行时版本编译了所有Hadoop JAR。仍在使用Java 7或更低版本的用户必须升级到Java 8。
2. 支持HDFS中的纠删码
纠删码是一种持久存储数据的方法,可节省大量空间。与标准HDFS副本机制的3倍开销相比,像Reed-Solomon(10,4) 这样的标准编码的空间开销是1.4倍。
由于纠删码在重建期间会带来额外的开销,并且大多数情况下会执行远程读取,因此传统上已将其用于存储较冷,访问频率较低的数据。
在部署此功能时应考虑纠删码机制的网络和CPU开销。
3. Shell脚本重写
Hadoop Shell脚本已被重写,以修复许多长期存在的错误并包括一些新功能。Hadoop的开发人员尽管一直在寻求兼容性,但是某些更改可能会破坏现有的安装。
4. MapReduce 任务本地优化
MapReduce 增加了对 map output 收集器的本地执行的支持,对于 shuffle 密集型工作,这可以使性能提高30%或更多。
5. 支持两个以上的 NameNode
在之前的版本中,HDFS的高可用最多支持两个NameNode。在HDFS 3.x 版本中,通过将编辑复制到法定数量的三个JournalNode,该体系结构能够容忍系统中任何一个节点的故障。
但是,某些部署需要更高的容错度。这个新特性启用了这一点,该功能允许用户运行多个备用NameNode。例如,通过配置三个NameNode和五个JournalNode,群集可以忍受两个节点的故障,而不仅仅是一个节点的故障。
6. 多个服务的默认端口已更改
以前,多个Hadoop服务的默认端口在Linux临时端口范围内(32768-61000)。这意味着在启动时,服务有时会由于与另一个应用程序的冲突而无法绑定到端口。
这些冲突的端口已移出临时范围,具体的端口更改如下:
NameNode 的端口: 50070 --> 9870, 8020 --> 9820, 50470 --> 9871; Secondary NameNode 的端口: 50091 --> 9869, 50090 --> 9868; DataNode 的端口: 50020 --> 9867, 50010 --> 9866, 50475 --> 9865, 50075 --> 9864; Hadoop KMS 的端口: 16000 --> 9600(HBase的HMaster端口号与Hadoop KMS端口号冲突。两者都使用16000,因此 Hadoop KMS 更改为9600)。
7. 支持Microsoft Azure数据湖和阿里云对象存储系统文件系统连接器
Hadoop现在支持与Microsoft Azure数据湖和Aliyun对象存储系统集成,作为与Hadoop兼容的替代文件系统。
8. 数据内节点平衡器
单个DataNode可管理多个磁盘。在正常的写操作过程中,磁盘将被均匀填充。但是,添加或替换磁盘可能会导致DataNode内部出现严重偏差。原有的HDFS平衡器无法处理这种情况。新版本的HDFS中有平衡功能处理,该功能通过hdfs diskbalancer CLI调用。
9. 基于HDFS路由器的联合
基于HDFS路由器的联合添加了一个RPC路由层,该层提供了多个HDFS名称空间的联合视图。这简化了现有HDFS客户端对联合群集的访问。
10. YARN资源类型
YARN资源模型已被通用化,以支持用户定义的CPU和内存以外的可计数资源类型。例如,集群管理员可以定义资源,例如GPU,软件许可证或本地连接的存储。然后可以根据这些资源的可用性来调度YARN任务。
2. HDFS 3.x 数据存储新特性-纠删码
HDFS是一个高吞吐、高容错的分布式文件系统,但是HDFS在保证高容错的同时也带来了高昂的存储成本,比如有5T的数据存储在HDFS上,按照HDFS的默认3副本机制,将会占用15T的存储空间。那么有没有一种能达到和副本机制相同的容错能力但是能大幅度降低存储成本的机制呢,有,就是在HDFS 3.x 版本引入的纠删码机制。
1. EC介绍
Erasure Coding 简称 EC,中文名:纠删码
EC(纠删码)是一种编码技术,在 HDFS 之前,这种编码技术在廉价磁盘冗余阵列(RAID)中应用最广泛,RAID 通过条带化技术实现 EC,条带化技术就是一种自动将 I/O 的负载均衡到多个物理磁盘上的技术,原理就是将一块连续的数据分成很多小部分并把他们分别存储到不同磁盘上去,这就能使多个进程同时访问数据的多个不同部分而不会造成磁盘冲突(当多个进程同时访问一个磁盘时,可能会出现磁盘冲突),而且在需要对这种数据进行顺序访问的时候可以获得最大程度上的 I/O 并行能力,从而获得非常好的性能。
在HDFS中,把连续的数据分成很多的小部分称为条带化单元,对于原始数据单元的每个条带单元,都会计算并存储一定数量的奇偶检验单元,计算的过程称为编码,可以通过基于剩余数据和奇偶校验单元的解码计算来恢复任何条带化单元上的错误。
2. HDFS数据冗余存储策略
HDFS的存储策略是副本机制,这种存储方式使得数据存储的安全性得到提高,但同时也带来了额外的开销,HDFS默认的3副本方案在存储空间和其他资源(如网络带宽)上有200%的额外开销,但是对于I/O活动相对较低的数据,在正常期间很少访问其他块副本,但是仍然消耗与第一个副本相同的资源量。
因此,HDFS 3.x 版本一个重大改进就是使用纠删码(EC)代替副本机制,纠删码技术提供了与副本机制相同的容错能力,而存储空间却少得多。在典型的纠删码(EC)设置中,存储开销不超过50%。
3. EC算法实现原理
EC的实现算法有很多种,较为常见的一种算法是Reed-Solomon(RS),它有两个参数,记为RS(k,m),k 表示数据块,m 表示校验块,有多少个校验块就最多可容忍多少个块(包括数据块和校验块)丢失,具体原理通过如下例子解释:
我们使用RS(3,2),表示使用 3 个原始数据块,2 个校验块。
例:由RS(3,2) 可求出它的生成矩阵 GT,和 7、8、9 三个原始数据块 Data,通过矩阵乘法,计算出来两个校验数据块 50、122。这时原始数据加上校验数据,一共五个数据块:7、8、9、50、122,可以任意丢两个,然后通过算法进行恢复,矩阵乘法如下图所示:
notion image
矩阵乘法
GT 是生成矩阵,RS(k,m) 的生成矩阵就是 m 行 k 列的矩阵; Data 代表原始数据,7,8,9代表原始数据块; Parity 代表校验数据,50,122代表校验数据块。
所以3个原始数据块,如果使用2个校验块,EC编码总共占用5个数据块的磁盘空间,与2副本机制占用6个数据块的磁盘空间容错能力相当。
4. EC的应用场景
将EC技术集成进HDFS可以提高存储效率,同时仍提供与传统的基于副本的HDFS部署类似的数据持久性。例如,一个具有6个块的3副本文件将消耗 6 * 3 = 18 个磁盘空间。但是,使用EC(6个数据,3个校验)部署时,它将仅消耗9个磁盘空间块。
但是EC在编码过程及数据重建期间会大量的使用CPU资源,并且数据大部分是执行远程读取,所以还会有大量的网络开销。
所以,对于CPU资源紧张且存储成本较低的情况下,可以采用副本机制存储数据,对于CPU资源有剩余且存储成本较高的情况下,可以采用EC机制存储数据。
5. EC在HDFS的架构
HDFS 是直接使用 Online EC(以EC格式写入数据),避免了转换阶段并节省了存储空间。Online EC 还通过并行利用多个磁盘主轴来增强顺序I/O性能。在具有高端网络的群集中,这尤其理想。其次,它自然地将一个小文件分发到多个DataNode,而无需将多个文件捆绑到一个编码组中。这极大地简化了文件操作,例如删除,磁盘配额以及namespaces之间的迁移。
在一般HDFS集群中,小文件可占总存储消耗的3/4以上,为了更好的支持小文件,HDFS目前支持条形布局(Striping Layout)的EC方案,而HDFS连续布局(Contiguous Layout)方案正在开发中。
1条形布局:
notion image
条形布局
优点:
●客户端缓存数据较少;
●无论文件大小都适用。
缺点:
●会影响一些位置敏感任务的性能,因为原先在一个节点上的块被分散到了多个不同的节点上;
●和多副本存储策略转换比较麻烦。
1连续布局:
notion image
连续布局
优点:
●容易实现;
●方便和多副本存储策略进行转换。
缺点:
●需要客户端缓存足够的数据块;
●不适合存储小文件。
传统模式下 HDFS 中文件的基本构成单位是block,而EC模式下文件的基本构成单位是block group。以RS(3,2)为例,每个block group包含3个数据块,2个校验块。
HDFS对于引入EC模式所做的主要扩展如下:
●NameNode:HDFS文件在逻辑上由block group组成,每个block group包含一定数量的内部块,为了减少这些内部块对NameNode内存消耗,HDFS引入了新的分层块命名协议。可以从其任何内部块的ID推断出block group的ID。这允许在块组而不是块的级别进行管理。
●Client:客户端读取和写入路径得到了增强,可以并行处理block group中的多个内部块。
●DataNode:DataNode运行额外ErasureCodingWorker(ECWorker)任务,用于对失败的纠删编码块进行后台恢复。NameNode检测到失败的EC块, 会选择一个DataNode进行恢复工作。此过程类似于失败时如何重新恢复副本的块。重建执行三个关键的任务节点:
a从源节点读取数据:使用专用线程池从源节点并行读取输入数据。基于EC策略,对所有源目标的发起读取请求,并仅读取最少数量的输入块进行重建。
b解码数据并生成输出数据:从输入数据解码新数据和奇偶校验块。所有丢失的数据和奇偶校验块一起解码。
c将生成的数据块传输到目标节点:解码完成后,恢复的块将传输到目标DataNodes。
●纠删码策略:为了适应异构的工作负载,HDFS群集中的文件和目录允许具有不同的复制和纠删码策略。纠删码策略封装了如何对文件进行编码/解码。每个策略由以下信息定义:
aEC模式:这包括EC组(例如6 + 3)中的数据和奇偶校验块的数量,以及编解码器算法(例如Reed-Solomon,XOR)。
b条带化单元的大小。这确定了条带读取和写入的粒度,包括缓冲区大小和编码工作。
我们可以通过XML文件定义自己的EC策略,该文件必须包含以下三个部分:
1layoutversion:这表示EC策略XML文件格式的版本。
2schemas:这包括所有用户定义的EC模式。
3policies:这包括所有用户定义的EC策略,每个策略均由schema id和条带化单元的大小(cellsize)组成。
Hadoop conf目录中有一个配置EC策略的XML示例文件,配置时可以参考该文件,文件名称为user_ec_policies.xml.template。
6. 集群的硬件配置
纠删码对群集在CPU和网络方面有一定的要求:
1编码和解码工作会消耗HDFS客户端和DataNode上的额外CPU。
2纠删码文件也分布在整个机架上,以实现机架容错。这意味着在读写条带化文件时,大多数操作都是在机架上进行的。因此,网络二等分带宽非常重要。
3对于机架容错,拥有至少与配置的EC条带宽度一样多的机架也很重要。对于EC策略RS(6,3),这意味着最少要有9个机架,理想情况下是10或11个机架,以处理计划内和计划外的中断。对于机架少于条带宽度的群集,HDFS无法保持机架容错,但仍会尝试在多个节点之间分布条带化文件以保留节点级容错。
7. 最后
在HDFS默认情况下,所有的EC策略是被禁止的,我们可以根据群集的大小和所需的容错属性,通过hdfs ec [-enablePolicy -policy]命令启用EC策略。
例如,对于具有9个机架的群集,像RS-10-4-1024k这样的策略将不会保留机架级的容错能力,而RS-6-3-1024k或RS-3-2-1024k可能更合适。
RS-10-4-1024k 表示有10个数据块,4个校验块。
在副本机制下,我们可以设置副本因子,指定副本的数量,但是在EC策略下,指定副本因子是没有意义的,因为它始终为1,无法通过相关命令进行更改。
五、Hadoop大厂面试真题
hadoop中常问的就三块,第一:分布式存储(HDFS);第二:分布式计算框架(MapReduce);第三:资源调度框架(YARN)。
1. 请说下HDFS读写流程
这个问题虽然见过无数次,面试官问过无数次,还是有不少面试者不能完整的说出来,所以请务必记住。并且很多问题都是从HDFS读写流程中引申出来的。
HDFS写流程:
1Client客户端发送上传请求,通过RPC与NameNode建立通信,NameNode检查该用户是否有上传权限,以及上传的文件是否在HDFS对应的目录下重名,如果这两者有任意一个不满足,则直接报错,如果两者都满足,则返回给客户端一个可以上传的信息;
2Client根据文件的大小进行切分,默认128M一块,切分完成之后给NameNode发送请求第一个block块上传到哪些服务器上;
3NameNode收到请求之后,根据网络拓扑和机架感知以及副本机制进行文件分配,返回可用的DataNode的地址;
注:Hadoop在设计时考虑到数据的安全与高效, 数据文件默认在HDFS上存放三份, 存储策略为本地一份,
同机架内其它某一节点上一份, 不同机架的某一节点上一份。
4客户端收到地址之后与服务器地址列表中的一个节点如A进行通信,本质上就是RPC调用,建立pipeline,A收到请求后会继续调用B,B在调用C,将整个pipeline建立完成,逐级返回Client;
5Client开始向A上发送第一个block(先从磁盘读取数据然后放到本地内存缓存),以packet(数据包,64kb)为单位,A收到一个packet就会发送给B,然后B发送给C,A每传完一个packet就会放入一个应答队列等待应答;
6数据被分割成一个个的packet数据包在pipeline上依次传输,在pipeline反向传输中,逐个发送ack(命令正确应答),最终由pipeline中第一个DataNode节点A将pipelineack发送给Client;
7当一个block传输完成之后, Client再次请求NameNode上传第二个block,NameNode重新选择三台DataNode给Client。
HDFS读流程:
1Client向NameNode发送RPC请求。请求文件block的位置;
2NameNode收到请求之后会检查用户权限以及是否有这个文件,如果都符合,则会视情况返回部分或全部的block列表,对于每个block,NameNode都会返回含有该block副本的DataNode地址;这些返回的DataNode地址,会按照集群拓扑结构得出DataNode与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的DataNode状态为STALE,这样的排靠后;
3Client选取排序靠前的DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性);
4底层上本质是建立Socket Stream(FSDataInputStream),重复的调用父类DataInputStream的read方法,直到这个块上的数据读取完毕;
5当读完列表的block后,若文件读取还没有结束,客户端会继续向NameNode 获取下一批的block列表;
6读取完一个block都会进行checksum验证,如果读取DataNode时出现错误,客户端会通知NameNode,然后再从下一个拥有该block副本的DataNode 继续读;
7read方法是并行的读取block信息,不是一块一块的读取;NameNode只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;
8最终读取来所有的block会合并成一个完整的最终文件;
2. HDFS在读取文件的时候,如果其中一个块突然损坏了怎么办
客户端读取完DataNode上的块之后会进行checksum验证,也就是把客户端读取到本地的块与HDFS上的原始块进行校验,如果发现校验结果不一致,客户端会通知NameNode,然后再从下一个拥有该block副本的DataNode继续读。
3. HDFS在上传文件的时候,如果其中一个DataNode突然挂掉了怎么办
客户端上传文件时与DataNode建立pipeline管道,管道的正方向是客户端向DataNode发送的数据包,管道反向是DataNode向客户端发送ack确认,也就是正确接收到数据包之后发送一个已确认接收到的应答。
当DataNode突然挂掉了,客户端接收不到这个DataNode发送的ack确认,客户端会通知NameNode,NameNode检查该块的副本与规定的不符,NameNode会通知DataNode去复制副本,并将挂掉的DataNode作下线处理,不再让它参与文件上传与下载。
4. NameNode在启动的时候会做哪些操作
NameNode数据存储在内存和本地磁盘,本地磁盘数据存储在fsimage镜像文件和edits编辑日志文件。
首次启动NameNode:
1格式化文件系统,为了生成fsimage镜像文件;
2启动NameNode:
○读取fsimage文件,将文件内容加载进内存
○等待DataNade注册与发送block report
3启动DataNode:
○向NameNode注册
○发送block report
○检查fsimage中记录的块的数量和block report中的块的总数是否相同
4对文件系统进行操作(创建目录,上传文件,删除文件等):
○此时内存中已经有文件系统改变的信息,但是磁盘中没有文件系统改变的信息,此时会将这些改变信息写入edits文件中,edits文件中存储的是文件系统元数据改变的信息。
第二次启动NameNode:
1读取fsimage和edits文件;
2将fsimage和edits文件合并成新的fsimage文件;
3创建新的edits文件,内容开始为空;
4启动DataNode。
5. Secondary NameNode了解吗,它的工作机制是怎样的
Secondary NameNode是合并NameNode的edit logs到fsimage文件中;
它的具体工作机制:
1Secondary NameNode询问NameNode是否需要checkpoint。直接带回NameNode是否检查结果;
2Secondary NameNode请求执行checkpoint;
3NameNode滚动正在写的edits日志;
4将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode;
5Secondary NameNode加载编辑日志和镜像文件到内存,并合并;
6生成新的镜像文件fsimage.chkpoint;
7拷贝fsimage.chkpoint到NameNode;
8NameNode将fsimage.chkpoint重新命名成fsimage;
所以如果NameNode中的元数据丢失,是可以从Secondary NameNode恢复一部分元数据信息的,但不是全部,因为NameNode正在写的edits日志还没有拷贝到Secondary NameNode,这部分恢复不了。
6. Secondary NameNode不能恢复NameNode的全部数据,那如何保证NameNode数据存储安全
这个问题就要说NameNode的高可用了,即 NameNode HA。
一个NameNode有单点故障的问题,那就配置双NameNode,配置有两个关键点,一是必须要保证这两个NameNode的元数据信息必须要同步的,二是一个NameNode挂掉之后另一个要立马补上。
1元数据信息同步在 HA 方案中采用的是“共享存储”。每次写文件时,需要将日志同步写入共享存储,这个步骤成功才能认定写文件成功。然后备份节点定期从共享存储同步日志,以便进行主备切换。
2监控NameNode状态采用zookeeper,两个NameNode节点的状态存放在zookeeper中,另外两个NameNode节点分别有一个进程监控程序,实施读取zookeeper中有NameNode的状态,来判断当前的NameNode是不是已经down机。如果Standby的NameNode节点的ZKFC发现主节点已经挂掉,那么就会强制给原本的Active NameNode节点发送强制关闭请求,之后将备用的NameNode设置为Active。
如果面试官再问HA中的 共享存储 是怎么实现的知道吗? 可以进行解释下:NameNode 共享存储方案有很多,比如Linux HA, VMware FT, QJM等,目前社区已经把由Clouderea公司实现的基于QJM(Quorum Journal Manager)的方案合并到HDFS的trunk之中并且作为默认的共享存储实现。 基于QJM的共享存储系统主要用于保存EditLog,并不保存FSImage文件。FSImage文件还是在NameNode的本地磁盘上。 QJM共享存储的基本思想来自于Paxos算法,采用多个称为JournalNode的节点组成的JournalNode集群来存储EditLog。每个JournalNode保存同样的EditLog副本。每次NameNode写EditLog的时候,除了向本地磁盘写入 EditLog 之外,也会并行地向JournalNode集群之中的每一个JournalNode发送写请求,只要大多数的JournalNode节点返回成功就认为向JournalNode集群写入EditLog成功。如果有2N+1台JournalNode,那么根据大多数的原则,最多可以容忍有N台JournalNode节点挂掉。
7. 在NameNode HA中,会出现脑裂问题吗?怎么解决脑裂
假设 NameNode1 当前为 Active 状态,NameNode2 当前为 Standby 状态。如果某一时刻 NameNode1 对应的 ZKFailoverController 进程发生了“假死”现象,那么 Zookeeper 服务端会认为 NameNode1 挂掉了,根据前面的主备切换逻辑,NameNode2 会替代 NameNode1 进入 Active 状态。但是此时 NameNode1 可能仍然处于 Active 状态正常运行,这样 NameNode1 和 NameNode2 都处于 Active 状态,都可以对外提供服务。这种情况称为脑裂。
脑裂对于NameNode这类对数据一致性要求非常高的系统来说是灾难性的,数据会发生错乱且无法恢复。zookeeper社区对这种问题的解决方法叫做 fencing,中文翻译为隔离,也就是想办法把旧的 Active NameNode 隔离起来,使它不能正常对外提供服务。
在进行 fencing 的时候,会执行以下的操作:
1首先尝试调用这个旧 Active NameNode 的 HAServiceProtocol RPC 接口的 transitionToStandby 方法,看能不能把它转换为 Standby 状态。
2如果 transitionToStandby 方法调用失败,那么就执行 Hadoop 配置文件之中预定义的隔离措施,Hadoop 目前主要提供两种隔离措施,通常会选择 sshfence:
○sshfence:通过 SSH 登录到目标机器上,执行命令 fuser 将对应的进程杀死;
○shellfence:执行一个用户自定义的 shell 脚本来将对应的进程隔离。
8. 小文件过多会有什么危害,如何避免
Hadoop上大量HDFS元数据信息存储在NameNode内存中,因此过多的小文件必定会压垮NameNode的内存。
每个元数据对象约占150byte,所以如果有1千万个小文件,每个文件占用一个block,则NameNode大约需要2G空间。如果存储1亿个文件,则NameNode需要20G空间。
显而易见的解决这个问题的方法就是合并小文件,可以选择在客户端上传时执行一定的策略先合并,或者是使用Hadoop的CombineFileInputFormat<K,V>实现小文件的合并。
9. 请说下HDFS的组织架构
1Client:客户端
○切分文件。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行存储
○与NameNode交互,获取文件的位置信息
○与DataNode交互,读取或者写入数据
○Client提供一些命令来管理HDFS,比如启动关闭HDFS、访问HDFS目录及内容等
2NameNode:名称节点,也称主节点,存储数据的元数据信息,不存储具体的数据
○管理HDFS的名称空间
○管理数据块(Block)映射信息
○配置副本策略
○处理客户端读写请求
3DataNode:数据节点,也称从节点。NameNode下达命令,DataNode执行实际的操作
○存储实际的数据块
○执行数据块的读/写操作
4Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务
○辅助NameNode,分担其工作量
○定期合并Fsimage和Edits,并推送给NameNode
○在紧急情况下,可辅助恢复NameNode
10. 请说下MR中Map Task的工作机制
简单概述:
inputFile通过split被切割为多个split文件,通过Record按行读取内容给map(自己写的处理逻辑的方法) ,数据被map处理完之后交给OutputCollect收集器,对其结果key进行分区(默认使用的hashPartitioner),然后写入buffer,每个map task 都有一个内存缓冲区(环形缓冲区),存放着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式溢写到磁盘,当整个map task 结束后再对磁盘中这个maptask产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task的拉取。
详细步骤:
1读取数据组件 InputFormat (默认 TextInputFormat) 会通过 getSplits 方法对输入目录中的文件进行逻辑切片规划得到 block,有多少个 block就对应启动多少个 MapTask。
2将输入文件切分为 block 之后,由 RecordReader 对象 (默认是LineRecordReader) 进行读取,以 \n 作为分隔符, 读取一行数据, 返回 <key,value>, Key 表示每行首字符偏移值,Value 表示这一行文本内容。
3读取 block 返回 <key,value>, 进入用户自己继承的 Mapper 类中,执行用户重写的 map 函数,RecordReader 读取一行这里调用一次。
4Mapper 逻辑结束之后,将 Mapper 的每条结果通过 context.write 进行collect数据收集。在 collect 中,会先对其进行分区处理,默认使用 HashPartitioner。
5接下来,会将数据写入内存,内存中这片区域叫做环形缓冲区(默认100M),缓冲区的作用是 批量收集 Mapper 结果,减少磁盘 IO 的影响。我们的 Key/Value 对以及 Partition 的结果都会被写入缓冲区。当然,写入之前,Key 与 Value 值都会被序列化成字节数组。
6当环形缓冲区的数据达到溢写比列(默认0.8),也就是80M时,溢写线程启动,需要对这 80MB 空间内的 Key 做排序 (Sort)。排序是 MapReduce 模型默认的行为,这里的排序也是对序列化的字节做的排序。
7合并溢写文件,每次溢写会在磁盘上生成一个临时文件 (写之前判断是否有 Combiner),如果 Mapper 的输出结果真的很大,有多次这样的溢写发生,磁盘上相应的就会有多个临时文件存在。当整个数据处理结束之后开始对磁盘中的临时文件进行 Merge 合并,因为最终的文件只有一个写入磁盘,并且为这个文件提供了一个索引文件,以记录每个reduce对应数据的偏移量。
11. 请说下MR中Reduce Task的工作机制
简单描述:
Reduce 大致分为 copy、sort、reduce 三个阶段,重点在前两个阶段。
copy 阶段包含一个 eventFetcher 来获取已完成的 map 列表,由 Fetcher 线程去 copy 数据,在此过程中会启动两个 merge 线程,分别为 inMemoryMerger 和 onDiskMerger,分别将内存中的数据 merge 到磁盘和将磁盘中的数据进行 merge。待数据 copy 完成之后,copy 阶段就完成了。
开始进行 sort 阶段,sort 阶段主要是执行 finalMerge 操作,纯粹的 sort 阶段,完成之后就是 reduce 阶段,调用用户定义的 reduce 函数进行处理。
详细步骤:
1Copy阶段:简单地拉取数据。Reduce进程启动一些数据copy线程(Fetcher),通过HTTP方式请求maptask获取属于自己的文件(map task 的分区会标识每个map task属于哪个reduce task ,默认reduce task的标识从0开始)。
2Merge阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。merge有三种形式:内存到内存;内存到磁盘;磁盘到磁盘。默认情况下第一种形式不启用。当内存中的数据量到达一定阈值,就直接启动内存到磁盘的merge。与map端类似,这也是溢写的过程,这个过程中如果你设置有Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。内存到磁盘的merge方式一直在运行,直到没有map端的数据时才结束,然后启动第三种磁盘到磁盘的merge方式生成最终的文件。
3合并排序:把分散的数据合并成一个大的数据后,还会再对合并后的数据排序。
4对排序后的键值对调用reduce方法:键相等的键值对调用一次reduce方法,每次调用会产生零个或者多个键值对,最后把这些输出的键值对写入到HDFS文件中。
12. 请说下MR中Shuffle阶段
shuffle阶段分为四个步骤:依次为:分区,排序,规约,分组,其中前三个步骤在map阶段完成,最后一个步骤在reduce阶段完成。
shuffle 是 Mapreduce 的核心,它分布在 Mapreduce 的 map 阶段和 reduce 阶段。一般把从 Map 产生输出开始到 Reduce 取得数据作为输入之前的过程称作 shuffle。
1Collect阶段:将 MapTask 的结果输出到默认大小为 100M 的环形缓冲区,保存的是 key/value,Partition 分区信息等。
2Spill阶段:当内存中的数据量达到一定的阀值的时候,就会将数据写入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置了 combiner,还会将有相同分区号和 key 的数据进行排序。
3MapTask阶段的Merge:把所有溢出的临时文件进行一次合并操作,以确保一个 MapTask 最终只产生一个中间数据文件。
4Copy阶段:ReduceTask 启动 Fetcher 线程到已经完成 MapTask 的节点上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上。
5ReduceTask阶段的Merge:在 ReduceTask 远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作。
6Sort阶段:在对数据进行合并的同时,会进行排序操作,由于 MapTask 阶段已经对数据进行了局部的排序,ReduceTask 只需保证 Copy 的数据的最终整体有效性即可。
Shuffle 中的缓冲区大小会影响到 mapreduce 程序的执行效率,原则上说,缓冲区越大,磁盘io的次数越少,执行速度就越快。 缓冲区的大小可以通过参数调整, 参数:mapreduce.task.io.sort.mb 默认100M
13. Shuffle阶段的数据压缩机制了解吗
在shuffle阶段,可以看到数据通过大量的拷贝,从map阶段输出的数据,都要通过网络拷贝,发送到reduce阶段,这一过程中,涉及到大量的网络IO,如果数据能够进行压缩,那么数据的发送量就会少得多。
hadoop当中支持的压缩算法: gzip、bzip2、LZO、LZ4、Snappy,这几种压缩算法综合压缩和解压缩的速率,谷歌的Snappy是最优的,一般都选择Snappy压缩。谷歌出品,必属精品。
14. 在写MR时,什么情况下可以使用规约
规约(combiner)是不能够影响任务的运行结果的局部汇总,适用于求和类,不适用于求平均值,如果reduce的输入参数类型和输出参数的类型是一样的,则规约的类可以使用reduce类,只需要在驱动类中指明规约的类即可。
15. YARN集群的架构和工作原理知道多少
YARN的基本设计思想是将MapReduce V1中的JobTracker拆分为两个独立的服务:ResourceManager和ApplicationMaster。
ResourceManager负责整个系统的资源管理和分配,ApplicationMaster负责单个应用程序的的管理。
1ResourceManager:RM是一个全局的资源管理器,负责整个系统的资源管理和分配,它主要由两个部分组成:调度器(Scheduler)和应用程序管理器(Application Manager)。
调度器根据容量、队列等限制条件,将系统中的资源分配给正在运行的应用程序,在保证容量、公平性和服务等级的前提下,优化集群资源利用率,让所有的资源都被充分利用应用程序管理器负责管理整个系统中的所有的应用程序,包括应用程序的提交、与调度器协商资源以启动ApplicationMaster、监控ApplicationMaster运行状态并在失败时重启它。
2ApplicationMaster:用户提交的一个应用程序会对应于一个ApplicationMaster,它的主要功能有:
○与RM调度器协商以获得资源,资源以Container表示。
○将得到的任务进一步分配给内部的任务。
○与NM通信以启动/停止任务。
○监控所有的内部任务状态,并在任务运行失败的时候重新为任务申请资源以重启任务。
3NodeManager:NodeManager是每个节点上的资源和任务管理器,一方面,它会定期地向RM汇报本节点上的资源使用情况和各个Container的运行状态;另一方面,他接收并处理来自AM的Container启动和停止请求。
4Container:Container是YARN中的资源抽象,封装了各种资源。一个应用程序会分配一个Container,这个应用程序只能使用这个Container中描述的资源。不同于MapReduceV1中槽位slot的资源封装,Container是一个动态资源的划分单位,更能充分利用资源。
16. YARN的任务提交流程是怎样的
当jobclient向YARN提交一个应用程序后,YARN将分两个阶段运行这个应用程序:一是启动ApplicationMaster;第二个阶段是由ApplicationMaster创建应用程序,为它申请资源,监控运行直到结束。具体步骤如下:
1用户向YARN提交一个应用程序,并指定ApplicationMaster程序、启动ApplicationMaster的命令、用户程序。
2RM为这个应用程序分配第一个Container,并与之对应的NM通讯,要求它在这个Container中启动应用程序ApplicationMaster。
3ApplicationMaster向RM注册,然后拆分为内部各个子任务,为各个内部任务申请资源,并监控这些任务的运行,直到结束。
4AM采用轮询的方式向RM申请和领取资源。
5RM为AM分配资源,以Container形式返回。
6AM申请到资源后,便与之对应的NM通讯,要求NM启动任务。
7NodeManager为任务设置好运行环境,将任务启动命令写到一个脚本中,并通过运行这个脚本启动任务。
8各个任务向AM汇报自己的状态和进度,以便当任务失败时可以重启任务。
9应用程序完成后,ApplicationMaster向ResourceManager注销并关闭自己。
17. YARN的资源调度三种模型了解吗
在Yarn中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,Fair Scheduler。
Apache版本的hadoop默认使用的是Capacity Scheduler调度方式。CDH版本的默认使用的是Fair Scheduler调度方式
FIFO Scheduler(先来先服务):
FIFO Scheduler把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
FIFO Scheduler是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞,比如有个大任务在执行,占用了全部的资源,再提交一个小任务,则此小任务会一直被阻塞。
Capacity Scheduler(能力调度器):
对于Capacity调度器,有一个专门的队列用来运行小任务,但是为小任务专门设置一个队列会预先占用一定的集群资源,这就导致大任务的执行时间会落后于使用FIFO调度器时的时间。
Fair Scheduler(公平调度器):
在Fair调度器中,我们不需要预先占用一定的系统资源,Fair调度器会为所有运行的job动态的调整系统资源。
比如:当第一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。
需要注意的是,在Fair调度器中,从第二个任务提交到获得资源会有一定的延迟,因为它需要等待第一个任务释放占用的Container。小任务执行完成之后也会释放自己占用的资源,大任务又获得了全部的系统资源。最终的效果就是Fair调度器即得到了高的资源利用率又能保证小任务及时完成。
上一篇
Hadoop基本概念(二):MapReduce
下一篇
Hadoop基本概念(四):版本更迭