Hadoop
Hadoop 组成架构
- HDFS: (分布式文件系统)
- MR: (并行计算框架)
- YARN: (资源协调者)
常用端口号
- Hadoop2.x
HDFS nameNode 内部通常端口 :8020/9000
HDFS nameNode 对用户的查询端口 : 50070
Yarn 查看任务运行情况的端口 : 8088
历史服务器:19888
常用配置文件
-
Hadoop 3.x
Core-site.xml
Hdfs-site.xnl
Yarn-site.xml
Mapred-site.xml
Workers -
Hadoop 2.x
Core-site.xml
Hdfs-site.xnl
Yarn-site.xml
Mapred-site.xml
slaves
HDFS
HDFS概念
- HDFS,它是一个分布式文件系统,用于存储文件,通过目录树来定位文件;
- HDFS的设计适合一次写入,多次读出的场景,且不支持文件的修改。
HDFS优缺点
- 优点:
- 高容错性
- 数据自动保存多个副本,可以通过增加副本的方式来提高容错性
- 副本丢失后可以自动恢复
- 适合处理大数据
- 数据规模:能够处理数据规模达到GB、TB、甚至PB级别的数据;
- 文件规模:能够处理百万规模以上的文件数量,数量相当之大。
- 可在廉价机器上通过多副本机制提升可靠性
- 高容错性
- 缺点:
- 不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。
- 无法高效的对大量小文件进行存储。
- 存储大量小文件的话,它会占用NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
- 小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
- 不支持并发写入、文件随机修改。
- 一个文件只能有一个写,不允许多个线程同时写;
- 仅支持数据append(追加),不支持文件的随机修改。
HDFS组成架构
Name Node
存储文件的元数据,如文件名,文件目录结构,文件属性(生成时间,副本数,文件权限),以及每个文件的块列表和块所在的DataNode 等
- 管理HDFS的名称空间 保存HDFS的元数据信息。
- 配置副本策略。
- 管理数据块(Block)的映射信息。
- 处理客户端的读写请求。
保存着HDFS的元数据信息以及数据块(block)的映射信息,处理客户端的读写请求
Data Node
在本地文件系统存储文件块数据,以及块数据的检验和
- 存储实际的数据块。
- 执行数据块的读写操作
Client
- Client将文件切分成一个个的Block,然后进行上传。
- 与Name Node交互,获取文件的位置信息。
- 与Data Node交互,读取或写入数据。
- 对hdfs进行增删改查
Secondary Name Node
每隔一段时间对nameNode 元数据备份
- 辅助Name Node。定期合并Fsimage和Edits,并推送给Name Node。
- 在紧急情况下,可辅助恢复Name Node。
NameNode 和 DataNode
HDFS 具有主/从架构。HDFS 集群由单个 NameNode 组成,这是一个管理文件系统命名空间并控制客户端对文件的访问的主服务器。此外,还有许多 DataNode,通常集群中每个节点一个,用于管理附加到它们运行的节点的存储。HDFS 公开了一个文件系统命名空间,并允许将用户数据存储在文件中。在内部,一个文件被分成一个或多个块,这些块存储在一组 DataNode 中。NameNode 执行文件系统命名空间操作,例如打开、关闭和重命名文件和目录。它还确定块到 DataNode 的映射。DataNode 负责处理来自文件系统客户端的读取和写入请求。DataNodes 还执行块创建、删除、
NameNode 和 DataNode 是设计用于在商品机器上运行的软件。这些机器通常运行 GNU/Linux 操作系统 (OS)。HDFS 是使用 Java 语言构建的;任何支持 Java 的机器都可以运行 NameNode 或 DataNode 软件。使用高度可移植的 Java 语言意味着 HDFS 可以部署在各种机器上。典型的部署有一台只运行 NameNode 软件的专用机器。集群中的每台其他机器都运行一个 DataNode 软件实例。该架构不排除在同一台机器上运行多个 DataNode,但在实际部署中很少出现这种情况。
集群中单个NameNode的存在极大地简化了系统的架构。NameNode 是所有 HDFS 元数据的仲裁者和存储库。该系统的设计方式是用户数据永远不会流经 NameNode。
The File System Namespace(文件系统命名空间)
HDFS 支持传统的分层文件组织。用户或应用程序可以创建目录并在这些目录中存储文件。文件系统命名空间层次结构类似于大多数其他现有文件系统;可以创建和删除文件、将文件从一个目录移动到另一个目录或重命名文件。HDFS 支持用户配额和访问权限。HDFS 不支持硬链接或软链接。但是,HDFS 架构并不排除实现这些功能。
虽然 HDFS 遵循FileSystem 的命名约定,但保留了一些路径和名称(例如/.reserved和.snapshot)。透明加密和快照等功能使用保留路径。
NameNode 维护文件系统命名空间。NameNode 记录对文件系统命名空间或其属性的任何更改。应用程序可以指定应该由 HDFS 维护的文件的副本数。文件的副本数称为该文件的复制因子。此信息由 NameNode 存储。
Data Replication(数据复制)
HDFS 旨在跨大型集群中的机器可靠地存储非常大的文件。它将每个文件存储为一系列块。复制文件的块以实现容错。每个文件的块大小和复制因子是可配置的。
文件中除最后一个块外的所有块大小相同,而在 append 和 hsync 中添加了对可变长度块的支持后,用户无需将最后一个块填充到配置的块大小即可开始一个新块。
应用程序可以指定文件的副本数。复制因子可以在文件创建时指定,以后可以更改。HDFS 中的文件是一次性写入的(追加和截断除外),并且在任何时候都严格只有一个写入器。
NameNode 做出有关块复制的所有决定。它定期从集群中的每个 DataNode 接收 Heartbeat 和 Blockreport。收到心跳意味着 DataNode 运行正常。Blockreport 包含 DataNode 上所有块的列表。
副本选择
为了最小化全局带宽消耗和读取延迟,HDFS 尝试满足来自离读取器最近的副本的读取请求。如果与读取器节点在同一机架上存在副本,则首选该副本来满足读取请求。如果 HDFS 集群跨越多个数据中心,则驻留在本地数据中心的副本优先于任何远程副本。
块放置策略
当复制因子为 3 时,HDFS 的放置策略是,如果 writer 在 datanode 上,则将一个副本放在本地机器上,否则在与 writer 相同机架的随机 datanode 上,另一个副本在节点上在不同的(远程)机架中,最后一个在同一远程机架中的不同节点上。如果复制因子大于 3,则随机确定第 4 个和后续副本的放置,同时保持每个机架的副本数低于上限(基本上是(副本 - 1)/机架 + 2)。除此之外,HDFS 还支持 4 种不同的可插拔块放置策略。用户可以根据他们的基础设施和用例选择策略。默认情况下,HDFS 支持 BlockPlacementPolicyDefault。
HDFS文件块大小
-
概念
HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dfs. blcoksize)来规定,默认是128M -
为什么不能设置太大,也不能设置太小
- 块设置太小,会增加寻址时间。
- 快设置太大,从磁盘传输数据的时间会明显大于定位这块开时位置所需的时间。导致程序在处理这块数据时,会非常慢。
-
总结
- 块的大小主要取决于磁盘的传输效率
命令行操作
序号 | 命令 | 作用 |
---|---|---|
1 | -help | 输出这个命令参数 |
2 | -ls | 显示目录信息 |
3 | -mkdir | 在HDFS上创建目录 |
4 | -moveFromLocal | 从本地剪切粘贴到HDFS |
5 | -appendToFile | 追加一个文件到已经存在的文件末尾 |
6 | -cat | 显示文件内容 |
7 | -chgrp 、-chmod、-chown | Linux文件系统中的用法一样,修改文件所属权限 |
8 | -copyFromLocal | 从本地文件系统中拷贝文件到HDFS路径去 |
9 | -copyToLocal | 从HDFS拷贝到本地 |
10 | -cp | 从HDFS的一个路径拷贝到HDFS的另一个路径 |
11 | -mv | 在HDFS目录中移动文件 |
12 | -get | 等同于copyToLocal,就是从HDFS下载文件到本地 |
13 | -getmerge | 合并下载多个文件 |
14 | -put | 等同于copyFromLocal |
15 | -tail | 显示一个文件的末尾 |
16 | -rm | 删除文件或文件夹 |
17 | -rmdir | 删除空目录 |
18 | -du | 统计文件夹的大小信息 |
19 | -setrep | 设置HDFS中文件的副本数量 |
20 | - expunge | 清空HDFS垃圾桶 |
HDFS 读写数据流程
HDFS写数据流程(重点)
- 客户端向Name Node请求上传文件,Name Node检查文件是否已存在
- Name Node返回是否可以上传。
- 客户端按照设定的块大小进行文件的切分
- 客户端请求第一个 Block上传到哪几个Data Node服务器上。
- Name Node返回Data Node节点
- 客户端向Data Node节点发送block传输请求
- Data Node建立block 传输通道
- 返回block 传输通道是否建立完成
- Client 开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
- 当一个block传输完成之后 客户端再次请求Name Node上传第二个Block的服务器。(重复执行3-7步)。
HDFS读数据流程(重点)
1)客户端向Name Node请求下载文件,Name Node通过查询元数据,找到文件块所在的Data Node地址。
2)挑选一台Data Node(就近原则,然后随机)服务器,请求读取数据。
3)Data Node开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。
4)客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。
副本节点选择(重点)
通常情况下,当复制因子为3时,HDFS的放置策略是将一个副本放在本地机架的一个节点上,另一个副本放在本地机架的另一个节点上,最后一个副本放在不同机架的另一个节点上。
网络拓扑节点距离计算
在HDFS写数据的过程中,NameNode会选择距离数据最近的DataNode接收数据。
节点距离:两个节点到达最近的共同祖先的距离总和
机架感知(副本存储节点选择)
- 第一个副本在 client所处的节点上。如果客户端在集群外,随机选一个
- 第二个副本在另一个机架上的随机一个节点
- 第三个副本在第二个副本所在机架的随机节点
文件系统元数据的持久性
- HDFS 命名空间由 NameNode 存储。NameNode 使用称为 EditLog 的事务日志来持久记录文件系统元数据发生的每个更改。例如,在 HDFS 中创建一个新文件会导致 NameNode 将一条记录插入到 EditLog 中来表明这一点。同样,更改文件的复制因子会导致将新记录插入到 EditLog 中。NameNode 使用其本地主机操作系统文件系统中的文件来存储 EditLog。整个文件系统命名空间,包括块到文件的映射和文件系统属性,都存储在一个名为 FsImage 的文件中。FsImage 也作为文件存储在 NameNode 的本地文件系统中。
- NameNode 在内存中保存了整个文件系统命名空间和文件 Blockmap 的图像。当 NameNode 启动,或者一个检查点被一个可配置的阈值触发时,它从磁盘读取 FsImage 和 EditLog,将 EditLog 中的所有事务应用到 FsImage 的内存表示中,并将这个新版本刷新到一个磁盘上的新 FsImage。然后它可以截断旧的 EditLog,因为它的事务已应用于持久 FsImage。这个过程称为检查点。检查点的目的是通过获取文件系统元数据的快照并将其保存到 FsImage 来确保 HDFS 具有文件系统元数据的一致视图。尽管读取 FsImage 是高效的,但直接对 FsImage 进行增量编辑并不高效。我们没有为每次编辑修改 FsImage,而是将编辑保存在 Editlog 中。在检查点期间,来自 Editlog 的更改将应用于 FsImage。可以在给定的时间间隔触发检查点(dfs.namenode.checkpoint.period)以秒表示,或者在累积给定数量的文件系统事务之后(dfs.namenode.checkpoint.txns)。如果设置了这两个属性,则要达到的第一个阈值会触发检查点。
- DataNode 将 HDFS 数据存储在其本地文件系统中的文件中。DataNode 不了解 HDFS 文件。它将每个 HDFS 数据块存储在其本地文件系统中的单独文件中。DataNode 不会在同一目录中创建所有文件。相反,它使用启发式方法来确定每个目录的最佳文件数并适当地创建子目录。在同一目录中创建所有本地文件并不是最佳选择,因为本地文件系统可能无法有效地支持单个目录中的大量文件。当 DataNode 启动时,它会扫描其本地文件系统,生成与这些本地文件对应的所有 HDFS 数据块的列表,并将此报告发送给 NameNode。该报告称为Blockreport。
平衡器(Balancer)
HDFS 数据可能并不总是均匀地放置在 DataNode 中。一个常见的原因是向现有集群添加新的 DataNode。在放置新块(文件的数据存储为一系列块)时,NameNode 在选择 DataNode 接收这些块之前会考虑各种参数。一些考虑是:
- 将块的副本之一保留在与正在写入块的节点相同的节点上的策略。
- 需要将块的不同副本分布在机架上,以便集群能够在整个机架丢失时幸免于难。
- 其中一个副本通常与写入文件的节点放置在同一机架上,以减少跨机架网络 I/O。
- 将 HDFS 数据均匀分布在集群中的 DataNode 上。
fsck
HDFS 支持 fsck 命令来检查各种不一致。它旨在报告各种文件的问题,例如,文件丢失块或复制不足的块。与用于本机文件系统的传统 fsck 实用程序不同,此命令不会更正它检测到的错误。通常 NameNode 会自动纠正大部分可恢复的故障。默认情况下,fsck 会忽略打开的文件,但会提供在报告期间选择所有文件的选项。HDFS fsck 命令不是 Hadoop shell 命令。它可以作为bin/hdfs fsck运行。有关命令用法,请参阅fsck。fsck 可以在整个文件系统或文件子集上运行。
恢复模式(Recovery Mode)
- 通常,您将配置多个元数据存储位置。然后,如果一个存储位置损坏,您可以从其他存储位置之一读取元数据。
- 但是,如果唯一可用的存储位置已损坏,您该怎么办?在这种情况下,有一种特殊的 NameNode 启动模式,称为恢复模式,可以让您恢复大部分数据。
- 您可以像这样在恢复模式下启动 NameNode:namenode -recover
- 当处于恢复模式时,NameNode 将在命令行中以交互方式提示您可以采取哪些措施来恢复数据。
- 如果您不想被提示,您可以提供-force选项。此选项将强制恢复模式始终选择第一个选项。通常,这将是最合理的选择。
- 因为恢复模式可能会导致您丢失数据,所以您应该在使用之前备份您的编辑日志和 fsimage。
检查点节点(Checkpoint Node)
- NameNode 使用两个文件来保存其命名空间:fsimage,它是命名空间的最新检查点和编辑,自检查点以来命名空间更改的日志(日志)。当 NameNode 启动时,它会合并 fsimage 和编辑日志以提供文件系统元数据的最新视图。NameNode 然后用新的 HDFS 状态覆盖 fsimage 并开始一个新的编辑日志。
- Checkpoint 节点定期创建命名空间的检查点。它从活动 NameNode 下载 fsimage 和编辑,在本地合并它们,然后将新图像上传回活动 NameNode。Checkpoint 节点通常运行在与 NameNode 不同的机器上,因为它的内存需求与 NameNode 的顺序相同。Checkpoint 节点由配置文件中指定的节点上的 bin/hdfs namenode -checkpoint 启动。
- 检查点(或备份)节点的位置及其随附的 Web 界面通过dfs.namenode.backup.address和dfs.namenode.backup.http-address配置变量进行配置。
- Checkpoint 节点上的检查点进程的启动由两个配置参数控制。
- dfs.namenode.checkpoint.period,默认设置为1小时,指定两个连续检查点之间的最大延迟
- dfs.namenode.checkpoint.txns默认设置为 100 万,定义 NameNode 上的未检查点事务的数量,这将强制执行紧急检查点,即使尚未达到检查点周期。
- Checkpoint 节点将最新的检查点存储在与 NameNode 目录结构相同的目录中。这允许检查点图像在必要时始终可供 NameNode 读取。请参阅导入检查点。
- 可以在集群配置文件中指定多个检查点节点。
Name Node中的元数据是存储在哪里的
- fsimage镜像文件和edits日志文件
- Fsimage : fsimage文件就是name Node所管理的元数据的信息,只不过是被序列化到磁盘上的镜像文件,因为name Node元数据信息都是存在内存中的,如果需要重启集群或者name node挂掉了,那内存中的数据就会被清空,就可以通过加载fsimage镜像文件将元数据信息反序列化到内存中。
- Edits: edits日志文件是记录了最近name node元数据的变化信息,比如添加或者删除了哪些文件,建立了那些目录之类的信息,主要用于和fsimage镜像合并为最新的fsimage,如果每次都直接将fsimage序列化到磁盘,这样会很浪费资源。
- 总结:
- Fsimage:Name Node内存中元数据序列化后形成的文件。
- Edits:记录客户端更新元数据信息的每一步操作(可通过Edits运算出元数据)
Name Node 和Secondary Name Node 工作机制
- Name Node启动:
- 首次启动需要格式化Name Node,创建Fsimage和Edits文件。如果不是第一次启动,直接加载Edits文件和Fsimage文件到内存。
- 客户端对元数据进行增删改的请求。
- Name Node记录操作日志,更新滚动日志。
- Name Node在内存中对元数据进行增删改。
- Secondary Name Node工作
- Secondary Name Node询问Name Node是否需要Check Point。直接带回Name Node是否检查结果。
- Secondary Name Node请求执行Check Point。
- Name Node滚动正在写的Edits日志。
- 将滚动前的Edits文件和Fsimage文件拷贝到Secondary Name Node。
- Secondary Name Node加载编辑日志和镜像文件到内存,并合并。
- 生成新的镜像文件fsimage.chkpoint。
- 拷贝fsimage.chkpoint到Name Node。
- Name Node将fsimage.chkpoint重新命名成fsimage。
Name Node 和Secondary Name Node 工作机制详解(重点!!!)
Fsimage :NameNode内存中元数据序列化后形成的文件。
Edits :记录客户端更新元数据信息的每一步操作(可通过Edits运算出元数据)。
Name Node启动时,先滚动Edits并生成一个空的edits.inprogress,然后加载Edits和Fsimage到内存中。当Client开始对Name Node发送元数据的增删改的请求时,这些请求的操作首先会被记录到edits.inprogress中,如果此时Name Node挂掉,重启后会从Edits中读取元数据的信息。然后,Name Node会在内存中执行元数据的增删改的操作。
由于Edits中记录的操作会越来越多,所以需要对Edits和Fsimage进行合并,将Edits和Fsimage加载到内存中形成新的Fsimage。Secondary Name Node的作用就是帮助Name Node进行Edits和Fsimage的合并工作。
Secondary Name Node会询问Name Node是否需要Check Point(当定时时间到和Edits中数据写满时触发Check Point合并操作)。带回Name Node是否检查结果。Secondary Name Node执行CheckPoint操作,会让Name Node滚动Edits并生成一个空的edits.inprogress,滚动Edits的目的是给Edits打个标记,以后所有新的操作都写入edits.inprogress,其他未合并的Edits和Fsimage会拷贝到Secondary Name Node的本地,然后将拷贝的Edits和Fsimage加载到内存中进行合并,生成fsimage.chkpoint,然后将fsimage.chkpoint拷贝给Name Node,重命名为Fsimage后替换掉原来的Fsimage。NameNode在启动时就只需要加载之前未合并的Edits和Fsimage即可,因为合并过的Edits中的元数据信息已经被记录在Fsimage中。
集群安全模式(什么是集群的安全模式)
-
NameNode启动时
当NameNode启动时,首先加载fsimage文件到内存,执行edits中的各项操作。一旦在内存中建立系统元数据的映像时,创建一个新的fsimage文件和一个空的edits文件。开始监听DataNode的请求。 -
DataNode启动时
当DataNode启动时 数据块的信息是以块列表的形式存储在DataNode中的,DataNode会向NameNode发送最新的块列表信息,当nameNode了解到足够的块信息后才能退出安全模式,即可高效运行文件系统
DataNode工作机制
- 数据块在DataNode上以文件形式存储的,一个是数据本身,一个是元数据
- DataNode启动后向NameNode注册,周期性(1小时)的向NameNode上报所有的块信息。
- 每3秒会有一次心跳,心跳返回结果带有NameNode给该DataNode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个DataNode的心跳,则认为该节点不可用。
- 集群运行中可以安全加入和退出一些机器
通讯协议
所有 HDFS 通信协议都建立在 TCP/IP 协议之上。客户端与 NameNode 机器上的可配置 TCP 端口建立连接。它与 NameNode 对话 ClientProtocol。DataNode 使用 DataNode 协议与 NameNode 对话。远程过程调用 (RPC) 抽象包装了客户端协议和数据节点协议。按照设计,NameNode 从不启动任何 RPC。相反,它只响应 DataNodes 或客户端发出的 RPC 请求。
健壮性
数据磁盘故障,心跳和重新复制(Data Disk Failure, Heartbeats and Re-Replication)
-
每个 DataNode 会定期向 NameNode 发送 Heartbeat(心跳) 消息。网络分区会导致 DataNode 的一个子集失去与 NameNode 的连接。NameNode 通过没有心跳消息来检测这种情况。NameNode 将没有最近 Heartbeat 的 DataNode 标记为已死,并且不会向它们转发任何新的 IO 请求。任何注册到死 DataNode 的数据都不再可用于 HDFS。DataNode 死亡可能会导致某些块的复制因子低于其指定值。NameNode 不断跟踪需要复制的块,并在必要时启动复制。重新复制的必要性可能由于多种原因而出现:DataNode 可能不可用,副本可能损坏,DataNode 上的硬盘可能发生故障,
-
标记 DataNodes 死亡的超时时间比较长(默认超过 10 分钟),以避免 DataNodes 状态波动引起的复制风暴。用户可以设置更短的时间间隔将 DataNodes 标记为陈旧,并通过配置对性能敏感的工作负载避免读取和/或写入过时的节点。
如何保证数据的完整性
对原始数据重新crc计算,然后和传输过来的crc校验位比较,看是否一致
- 当DataNode读取Block的时候,它会计算CheckSum(校验和)。
- 如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。
- Client读取其他DataNode上的Block。
- 常见的校验算法 crc(32) ,md5(128),shal(160)
- DataNode在其文件创建后周期验证CheckSum
元数据磁盘故障(Metadata Disk Failure)
FsImage 和 EditLog 是 HDFS 的中心数据结构。这些文件的损坏会导致 HDFS 实例无法运行。为此,NameNode 可以配置为支持维护 FsImage 和 EditLog 的多个副本。对 FsImage 或 EditLog 的任何更新都会导致每个 FsImage 和 EditLog 同步更新。FsImage 和 EditLog 的多个副本的这种同步更新可能会降低 NameNode 可以支持的每秒命名空间事务的速率。然而,这种降级是可以接受的,因为即使 HDFS 应用程序本质上是数据密集型的,它们也不是元数据密集型的。当一个 NameNode 重新启动时,它会选择最新的一致 FsImage 和 EditLog 来使用。
提高故障恢复能力的另一个选择是使用多个 NameNode 启用高可用性,或者使用NFS 上的共享存储或使用分布式编辑日志(称为日志)。后者是推荐的方法。
快照
快照支持在特定时刻存储数据副本。快照功能的一种用法可能是将损坏的 HDFS 实例回滚到先前已知的良好时间点。
hdfs 高可用性
Architecture(体系结构)
-
在典型的 HA 集群中,两台或多台独立的机器被配置为 NameNode。在任何时间点,只有一个 NameNode 处于Active状态,而其他 NameNode 处于Standby状态。Active NameNode 负责集群中的所有客户端操作,而 Standbys 只是充当工作人员,维护足够的状态以在必要时提供快速故障转移。
-
为了让备用节点保持与活动节点的状态同步,两个节点都与一组名为“JournalNodes”(JN)的独立守护进程通信。当主动节点执行任何命名空间修改时,它会将修改记录持久地记录到这些 JN 中的大多数。Standby 节点能够从 JN 中读取编辑,并不断地观察它们以了解对编辑日志的更改。当备用节点看到编辑时,它将它们应用到自己的命名空间。在发生故障转移的情况下,备用节点将确保它已从 JournalNodes 读取所有编辑,然后再将其提升为 Active 状态。这可确保在发生故障转移之前完全同步命名空间状态。
-
为了提供快速故障转移,备用节点还必须具有有关集群中块位置的最新信息。为了实现这一点,DataNode 配置了所有 NameNode 的位置,并向所有 NameNode 发送块位置信息和心跳。
-
一次只有一个 NameNode 处于活动状态对于 HA 集群的正确操作至关重要。否则,命名空间状态将很快在两者之间产生分歧,从而冒着数据丢失或其他不正确结果的风险。为了确保这个属性并防止所谓的“脑裂场景”,JournalNodes 将永远只允许一个 NameNode 一次成为写入者。在故障转移期间,将变为活动的 NameNode 将简单地接管写入 JournalNode 的角色,这将有效地防止另一个 NameNode 继续处于活动状态,从而允许新的 Active 安全地进行故障转移。
故障转移
自动故障转移向 HDFS 部署添加了两个新组件:ZooKeeper quorum 和 ZKFailoverController 进程(缩写为 ZKFC)。
- Apache ZooKeeper 是一种高度可用的服务,用于维护少量协调数据、通知客户端该数据的更改以及监控客户端的故障。自动 HDFS 故障转移的实现依赖于 ZooKeeper 进行以下操作:
- 故障检测——集群中的每台 NameNode 机器都在 ZooKeeper 中维护一个持久会话。如果机器崩溃,ZooKeeper 会话将过期,通知其他 NameNode 应该触发故障转移。
- Active NameNode 选举- ZooKeeper 提供了一种简单的机制来专门将节点选为活动节点。如果当前活动的 NameNode 崩溃,另一个节点可能会在 ZooKeeper 中获取特殊的排他锁,指示它应该成为下一个活动的。
- ZKFailoverController (ZKFC) 是一个新组件,它是一个 ZooKeeper 客户端,它还监视和管理 NameNode 的状态。每台运行 NameNode 的机器也运行一个 ZKFC,ZKFC 负责:
- 健康监控- ZKFC 使用健康检查命令定期 ping 其本地 NameNode。只要 NameNode 及时响应健康状态,ZKFC 就认为该节点是健康的。如果节点崩溃、冻结或以其他方式进入不健康状态,健康监视器会将其标记为不健康。
- ZooKeeper 会话管理- 当本地 NameNode 健康时,ZKFC 在 ZooKeeper 中保持一个打开的会话。如果本地 NameNode 处于活动状态,它还拥有一个特殊的“锁”znode。此锁使用 ZooKeeper 对“临时”节点的支持;如果会话过期,锁节点将被自动删除。
- 基于 ZooKeeper 的选举——如果本地 NameNode 是健康的,并且 ZKFC 看到当前没有其他节点持有锁 znode,它会自己尝试获取锁。如果成功,那么它“赢得了选举”,并负责运行故障转移以使其本地 NameNode 处于活动状态。故障转移过程类似于上面描述的手动故障转移:首先,如果需要,先前的活动被隔离,然后本地 NameNode 转换为活动状态。
MapReduce
MapReduce概述
- MapReduce 是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用” 的核心框架。
- MapReduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在hadoop集群上
MapReduce优缺点
- 优点:
- 易于编程。
- 良好扩展性:可以动态增加服务器,解决计算资源不够问题
- 高容错性。任何一台机器挂掉,可以将任务转移到其他节点
- 适合大数据量的计算(TB/PB)几千台服务器共同计算
- 缺点:
- 不擅长实时计算
- 不擅长流式计算
- 不擅长DAG有向无环图计算。
MapReduce组成部分
- Client
每个Job都会在用户端通过Client类将应用程序以及配置参数Configuration打包成JAR文件存储在HDFS中,并把路径提交到JobTracker的Master服务,然后由Master创建每一个Task(即MapTask和ReduceTask)将它们分发到各个TaskTracker服务中去执行。 - JobTracker
JobTracker负责资源监控和作业调度。监控所有TaskTracker与Job的健康状况,一旦发现失败,就将相应的任务转移到其他节点;同时,JobTracker会跟踪任务的执行进度、资源使用量等信息,并将这些信息告诉任务调度器,而调度器会在资源出现空闲时,选择合适的任务使用这些资源。在Hadoop中,任务调度器是一个可插拔的模块,用户可以根据自己的需要设计相应的调度器。 - TaskTracker
TaskTracker会周期性地通过Heartbeat(心跳)将本节点上资源的使用情况和任务的运行进度汇报给JobTracker,同时接收JobTracker发送过来的命令并执行相应的操作(如启动新任务、杀死任务等)。 TaskTracker使用“slot”来衡量划分本节点上的资源量。“slot”代表单位的计算资源(CPU、内存等)。一个Task获取到一个slot后才有机会运行,而Hadoop调度器的作用就是将各个TaskTracker上的空闲slot分配给Task使用。slot分为Map slot和Reduce slot两种,分别供Map Task和Reduce Task使用。TaskTracker通过slot数目(可配置参数)限定Task的并发度。 - Task
Task分为Map Task和Reduce Task两种,均由TaskTracker启动。HDFS以固定大小的block为基本单位存储数据,而对于MapReduce而言,其处理单位是split。
MapReduce核心思想
- MapReduce运行程序一般需要分为两个阶段:map阶段和reduce阶段
- Map阶段的并发mapTask,完全并行运行,互不相干
- Reduce阶段的并行reduceTask,完全互不相干,但是他们的数据依赖于上一阶段的所有mapTask并发实例的输出
- mapReduce编程模型只能包含一个map阶段和一个reduce阶段,如果用户的业务逻辑非常复杂,那么只能多个mapReduce程序,穿行运行
MapReduce进程
常用数据序列化类型
表4-1 常用的数据类型对应的Hadoop数据序列化类型
Java类型 | Hadoop Writable类型 |
---|---|
Boolean | BooleanWritable |
Byte | ByteWritable |
Int | IntWritable |
Float | FloatWritable |
Long | LongWritable |
Double | DoubleWritable |
String | Text |
Map | MapWritable |
Array | ArrayWritable |
MapReduce编程规范
用户编写的程序分成三个部分:Mapper、Reducer和Driver。
Hadoop 序列化
概述
自定义bean对象实现序列化接口(Writable)
(1)必须实现Writable接口
(2)反序列化时,需要反射调用空参构造函数,所以必须有空参构造
(3)重写序列化方法
(4)重写反序列化方法
(5)注意反序列化的顺序和序列化的顺序完全一致
(6)要想把结果显示在文件中,需要重写toString(),可用”\t”分开,方便后续用。
(7)如果需要将自定义的bean放在key中传输,则还需要实现Comparable接口,因为MapReduce框中的Shuffle过程要求对key必须能排序。详见后面排序案例。
切片与MapTask并行度决定机制
- MapTask并行度决定机制
- 数据块:Block是HDFS物理上把数据分成一块一块。
- 数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。
FileInputFormat切片机制
简单的按照文件的内容长度进行切片
切片大小,默认等于block大小
切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
FileInputFormat切片机制流程
- 程序先找到数据存储的目录
- 开始遍历处理(规划切片)目录下的每一个文件
- 遍历第一个文件ss.txt
- 获取文件大小 fs.sizeOf(ss.txt)
- 计算切片大小
computeSplitSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize = 128M - 默认情况下,切片大小=blocksize
- 开始切片 ,形成第一个切片 1-128MB 第二个切片 128-256MB 第三个切片 256-300M
(每次切片时,都要判断切完剩下的部分是否大于块的1.1倍,不大于1.1倍就划分为一块切片) - 将切片信息写到一个切片规划文件中
- 整个切片的核心过程在getSplit()方法中完成
- InputSplit 只记录了切片的元数据信息,比如起始位置,长度以及所在的节点列表等
- 提交切片规划文件到yarn上,yarn上的 MrAppMaster就可以根据切片规划文件计算开启MapTask个数
CombineTextInputFormat切片机制
框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
-
应用场景:
CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。 -
虚拟存储切片最大值设置
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
注意:虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值。 -
切片机制
生成切片过程包括:虚拟存储过程和切片过程二部分。
-
虚拟存储过程:
将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。
例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为4.02M,如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。 -
切片过程:
- 判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片。
- 如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
- 测试举例:有4个小文件大小分别为1.7M、5.1M、3.4M以及6.8M这四个小文件,则虚拟存储之后形成6个文件块,大小分别为:
1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)
最终会形成3个切片,大小分别为:
(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M
MapReduce工作流程(⭐⭐⭐⭐⭐)
map 阶段
- 首先有一个200M的待处理文件
- 切片:在客户端提交之前,根据参数配置,进行任务规划,将文件按128M每块进行切片
- 提交:提交可以提交到本地工作环境或者Yarn工作环境,本地只需要提交切片信息和xml配置文件,Yarn环境还需要提交jar包;本地环境一般只作为测试用
- 提交时会将每个任务封装为一个job交给Yarn来处理(详细见后边的Yarn工作流程介绍),计算出MapTask数量(等于切片数量),每个MapTask并行执行
- MapTask中执行Mapper的map方法,此方法需要k和v作为输入参数,所以会首先获取kv值;
- 首先调用InputFormat方法,默认为TextInputFormat方法,在此方法调用createRecoderReader方法,将每个块文件封装为k,v键值对,传递给map方法
- map方法首先进行一系列的逻辑操作,执行完成后最后进行写操作
- map方法如果直接写给reduce的话,相当于直接操作磁盘,太多的IO操作,使得效率太低,所以在map和reduce中间还有一个shuffle操作
- map处理完成相关的逻辑操作之后,首先通过outputCollector向环形缓冲区写入数据,环形缓冲区主要两部分,一部分写入文件的元数据信息,另一部分写入文件的真实内容
- 环形缓冲区的默认大小是100M,当缓冲的容量达到默认大小的80%时,进行反向溢写
- 在溢写之前会将缓冲区的数据按照指定的分区规则进行分区和排序,之所以反向溢写是因为这样就可以边接收数据边往磁盘溢写数据
- 在分区和排序之后,溢写到磁盘,可能发生多次溢写,溢写到多个文件
- 对所有溢写到磁盘的文件进行归并排序
- 在9到10步之间还可以有一个Combine合并操作,意义是对每个MapTask的输出进行局部汇总,以减少网络传输量
- Map阶段的进程数比Reduce阶段要多,所以放在Map阶段处理效率更高
- Map阶段合并之后,传递给Reduce的数据就会少很多
- 但是Combiner能够应用的前提是不能影响最终的业务逻辑,而且Combiner的输出kv要和Reduce的输入kv类型对应起来
在客户端提交之前,根据参数配置,进行任务规划,将文件按128M每块进行切片,提交时会将每个任务封装为一个job交给Yarn来处理,计算出MapTask数量,每个MapTask并行执行,MapTask中执行Mapper的map方法,首先调用InputFormat方法,默认为TextInputFormat方法,在此方法调用createRecoderReader方法,将每个块文件封装为k,v键值对,传递给map方法,map方法首先进行一系列的逻辑操作,执行完成后最后进行写操作,在map和reduce中间还有一个shuffle操作,map处理完成相关的逻辑操作之后,首先通过outputCollector向环形缓冲区写入数据,环形缓冲区主要两部分,一部分写入文件的元数据信息,另一部分写入文件的真实内容,环形缓冲区的默认大小是100M,当缓冲的容量达到默认大小的80%时,进行反向溢写,在溢写之前会将缓冲区的数据按照指定的分区规则进行分区和排序,在分区和排序之后,溢写到磁盘,可能发生多次溢写,溢写到多个文件,对所有溢写到磁盘的文件进行归并排序,有一个Combine合并操作,意义是对每个MapTask的输出进行局部汇总,以减少网络传输量
整个MapTask分为Read阶段,Map阶段,Collect阶段,溢写(spill)阶段和combine阶段
- Read阶段:MapTask通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value
- Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value
- Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中
- Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作
reduce 阶段
- 所有的MapTask任务完成后,启动相应数量的ReduceTask(和分区数量相同),并告知ReduceTask处理数据的范围
- ReduceTask会将MapTask处理完的数据拷贝一份到磁盘中,并合并文件和归并排序
- 最后将数据传给reduce进行处理,一次读取一组数据
- 最后通过OutputFormat输出
整个ReduceTask分为Copy阶段,Merge阶段,Sort阶段(Merge和Sort可以合并为一个),Reduce阶段。
- Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中
- Merge阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多
- Sort阶段:按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可
- Reduce阶段:reduce()函数将计算结果写到HDFS上
Shuffle机制
Map方法之后,Reduce方法之前的数据处理过程称之为Shuffle
Map方法之后,Reduce方法之前的数据处理过程称之为Shuffle。shuffle流程详解如下:
- MapTask收集map()方法输出的kv对,放到环形缓冲区中
- 从环形缓冲区不断溢出到本地磁盘文件,可能会溢出多个文件
- 多个溢出文件会被合并成大的溢出文件
- 在溢出过程及合并的过程中,都要调用Partitioner进行分区和针对key进行排序
- ReduceTask根据自己的分区号,去各个MapTask机器上取相应的结果分区数据
- ReduceTask将取到的来自同一个分区不同MapTask的结果文件进行归并排序
- 合并成大文件后,shuffle过程也就结束了,进入reduce方法
WritableComparabl
排序的分类
Combiner合并
MapTask工作机制
-
(1) Read阶段:MapTask通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value。
-
(2) Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。
-
(3) Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。
-
(4) Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作。
- 溢写阶段详情:
- 步骤1:利用快速排序算法对缓存区内的数据进行排序,排序方式是,先按照分区编号Partition进行排序,然后按照key进行排序。这样,经过排序后,数据以分区为单位聚集在一起,且同一分区内所有数据按照key有序。
- 步骤2:按照分区编号由小到大依次将每个分区中的数据写入任务工作目录下的临时文件output/spillN.out(N表示当前溢写次数)中。如果用户设置了Combiner,则写入文件之前,对每个分区中的数据进行一次聚集操作。
- 步骤3:将分区数据的元信息写到内存索引数据结构SpillRecord中,其中每个分区的元信息包括在临时文件中的偏移量、压缩前数据大小和压缩后数据大小。如果当前内存索引大小超过1MB,则将内存索引写到文件output/spillN.out.index中。
-
(5) Combine阶段:当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。
当所有数据处理完后,MapTask会将所有临时文件合并成一个大文件,并保存到文件output/file.out中,同时生成相应的索引文件output/file.out.index。
在进行文件合并过程中,MapTask以分区为单位进行合并。对于某个分区,它将采用多轮递归合并的方式。每轮合并io.sort.factor(默认10)个文件,并将产生的文件重新加入待合并列表中,对文件排序后,重复以上过程,直到最终得到一个大文件。
让每个MapTask最终只生成一个数据文件,可避免同时打开大量文件和同时读取大量小文件产生的随机读取带来的开销。
ReduceTask工作机制
- (1) Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中。
- (2) Merge阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。
- (3) Sort阶段:按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。
- (4) Reduce阶段:reduce()函数将计算结果写到HDFS上。
combine函数的作用
comnbine分为map端和reduce端,作用是把同一个key的键值对合并在一起,可以自定义的。combine函数把一个map函数产生的<key,value>对(多个key,value)合并成一个新的<key2,value2>。将新的<key2,value2>作为输入到reduce函数中。这个value2亦可称之为values,因为有多个。这个合并的母大是为了减少网络传输。
简列几条MapReduce的调优方法
MapReduce优化方法主要从六个方面考虑:数据输入,Map阶段,Reduce阶段,IO传输,数据倾斜问题和常用的调优参数。
-
数据输入
- 合并小文件,在执行MR任务前将小文件进行合并,大量的小文件会产生大量的map任务,增大map任务装载次数,而任务的装载比较耗时,从而导致MR运行较慢;
- 采用combinetextinputformat来作为输入,解决输入端大量小文件的场景。
-
Map阶段
- 减少溢写次数,通过调整io.sort.mb及sort.spill.percent参数值,增大出发溢写的内存上限,减少溢写次数,从而减少磁盘IO;
- 减少合并次数,通过调整io.sort.factor参数,增大merge的文件数目,减少merge的次数,从而缩减MR处理时间;
3)在map之后,不影响业务逻辑的前提下,先进行combine处理,减少IO。
-
Reduce阶段
- 合理设置map和reduce的数量,两个数量都不能太少或者太多,太少,会导致task等待时间太长,延长处理时间,太多,会导致map和reduce任务之间竞争资源,造成处理超时等错误;
- 设置map和reduce共存,调整,show start completedmaps参数,使map运行到一定程度后,reduce也开始运行,从而减少reduce等待时间;
- 规避使用reduce,因为reduce在用于连接数据集的时候会产生大量的网络消耗;
- 合理设置reduce端的buffer,可以通过设置参数来配置,使得buffer中的一部分数据可以直接输送到reduce,从而减少IO开销;MapReduce,Reduce.input.buffer.percent的默认为0.0,当值大于0时,会保留在指定比例的内存读buffer中的数据直接拿给reduce使用。
-
IO传输
- 采用数据压缩的方式,减少任务的IO时间;
- 使用seq二进制文件。
分片与分块的区别
- 分片是逻辑概念,分片有冗余。
- 分块是物理概念,是将数据拆分,无冗余。
数据切片与MapTask并行度决定机制
- 一个job的map阶段并行度由客户端子提交JOB时的切片数决定
- 每一个split切片分配一个mapTask并行实例处理
- 默认情况下,切片大小=BlockSize
- 切片时不考虑数据集整体,而是逐个针对每一个文件单独切片
计算切片大小的公式
Math.max(minSize,Math.min(maxSize,blocksize))
Hadoop 数据压缩
MR支持的压编码
压缩格式 | hadoop自带? | 算法 | 文件扩展名 | 是否可切分 | 换成压缩格式后,原来的程序是否需要修改 |
---|---|---|---|---|---|
DEFLATE | 是,直接使用 | DEFLATE | .deflate | 否 | 和文本处理一样,不需要修改 |
Gzip | 是,直接使用 | DEFLATE | .gz | 否 | 和文本处理一样,不需要修改 |
bzip2 | 是,直接使用 | bzip2 | .bz2 | 是 | 和文本处理一样,不需要修改 |
LZO | 否,需要安装 | LZO | .lzo | 是 | 需要建索引,还需要指定输入格式 |
Snappy | 否,需要安装 | Snappy | .snappy | 否 | 和文本处理一样,不需要修改 |
为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器,如下表所示。
压缩格式 | 对应的编码/解码器 |
---|---|
DEFLATE | org.apache.hadoop.io.compress.DefaultCodec |
gzip | org.apache.hadoop.io.compress.GzipCodec |
bzip2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compression.lzo.LzopCodec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
压缩性能的比较
压缩算法 | 原始文件大小 | 压缩文件大小 | 压缩速度 | 解压速度 |
---|---|---|---|---|
gzip | 8.3GB | 1.8GB | 17.5MB/s | 58MB/s |
bzip2 | 8.3GB | 1.1GB | 2.4MB/s | 9.5MB/s |
LZO | 8.3GB | 2.9GB | 49.3MB/s | 74.6MB/s |
压缩方式
总结:
Gzip:压缩解压速度快、压缩率高,不支持split切片
BZip2:压缩解压速度慢、压缩率高于Gzip、支持split 切片、支持多文件
LZO: 压缩解压速度快、压缩率低 于Gzip,支持splic 切片(需要建立索引,文件修改后需要重新建索引,并指定InputFormat 格式为LZO)
Snappy: 压缩速度快、压缩率低于Gzip,不支持splic切片
-
Gzip压缩
-
Bzip2压缩
-
Lzo压缩
-
Snappy压缩
如何使用 mapReduce 实现两个表的 join
1)reduce join : 在 map 阶段,map 函数同时读取两个文件 File1 和 File2,为了区分两种来源的 key/value 数据对,对每条数据打一个标签(tag),比如:tag=0 表示来自文件 File1,tag=2 表示来自文件 File2。 在 Reduce 端以连接字段作为 key 的分组已经完成,我们只需要在每一个分组当中将那些来源于不同文件的记录(在 Map 阶段已经打标志)分开,最后进行合并就 ok 了。
2)map join : Map side join 是针对以下场景进行的优化:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们就可以采用 DistributedCache的方法,具体看上一题:Hadoop 的缓存机制(Distributedcache)
YARN
Yarn概述
Yarn是一个资源管理系统和程序调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操作系统平台
Yarn 架构
Resource Manager
管理着整个集群的资源
他是集群中的主角色,程序的提交,程序的资源申请,包括资源之间的分配,都是由Resource Manager来决定的. 程序能不能提交上去,提交上去后能不能运行,又分配多少资源,这些都是由Resource Manager来管理的
主要功能有
(1)处理客户端请求
(2)启动或监控Application Master
(3)监控Node Manager
(4)资源的分配与调度
Resource Manager主要由两个组件构成
- 调度器(scheduler)
简单来理解的话就是 很多程序同时来申请资源 那么在集群资源有限的情况下,该如何去分配,这时候就需要一个调度器来进行负责,调度器需要自己的调度策略比如:
-
FIFO(先进先出调度器):
它先按照作业的优先级高低,再按照到达时间的先后选择被执行的作业
-
Capacity Scheduler(容量调度器):
支持多个队列,每个队列可配置一定的资源量,每个队列采用FIFO调度策略,为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源量进行限定 -
Fair Scheduler(公平调度器):
支持多队列多用户,每个队列中的资源量可以配置,同一队列中的作业公平共享队列中所有资源
- 应用程序管理器(Applications Manager)
负责应用程序的提交,与调度器做一些协调 并且还要监控Application Master的运行状态,当这个程序运行完成之后还有进行资源回收,在失败时重新启动 Application Master 容器的服务
Node Manager
他负责每台机器上的资源管理,他会根据Resource Manager的命令启动Container容器并且监视容器的资源使用情况,将这些情况汇报给Resource Manager
- 负责管理单个节点的资源使用
- 他需要定时定期的向Resource Manager汇报本节点的资源使用情况,以及各个container 的运行状态
- Node Manager配合Application Master进行容器(container)的启动和停止
Application Master
存在应用程序当中的,每一个应用程序都有自己的一个Application Master
相当于程序内部的老大,负责程序内部的资源申请,各个阶段之间的调度执行的情况
(1)负责数据的切分
(2)为应用程序申请资源并分配给内部的任务
(3)任务的监控与容错
向Resource Manager调度器协商获取资源(使用Container来表示)
将得到的资源进一步分配给内部的任务
分配到资源后需要向Node Manager通讯启动或者停止任务
还需要监控所有任务的运行状态,并在任务运行失败时重新为任务申请资源并重启任务
Container
Container 是yarn 中的资源抽象,他封装了某个节点上的资源,比如内存.CPU,磁盘。
当Application Master向Resource Manager申请资源时,返回的资源就是使用的Container 来表示的,YARN 会为每个任务分配一个Container ,并且该任务只能使用自己的Container 资源
YARN工作流程(⭐⭐⭐⭐⭐)
共分为五个阶段
作业提交阶段
- Client 向 Resource Manager 申请计算资源的应用,向整个集群提交job,同时申请一个job_id
- Resource Manager收到client 的请求后 给client 返回该job资源的提交路径.HDFS路径.和job_id ,每一个job都有一个唯一的id
- Client 收到Resource Manager 的返回后,根据这些返回数据的值发送jar包,切片信息和配置文件到指定的资源提交路径
- Client 提交完资源后向Resource Manager发送执行作业请求,Resource Manager在接收到这个请求后会针对这个job创建一个Application Manager 来管理这个job
作业初始化阶段
- 新创建的Application Manager会将job添加到Resource Scheduler(资源调度器中)resource Scheduler 维护了一个队列,所有要执行的job都会保存在这个队列中,按照一定的调度规则等待执行
- 当轮到我们的任务执行时,resource Scheduler(资源调度器)会通知Application Manager(应用程序管理器)告诉他有一个Node Manager可以用来执行job
- Application Manager(应用程序管理器)调用分配给他的Node Manager 开辟一个container(容器),并在这个container(容器)中启动对应的需要被执行的job 的Application Master
- Application Master获取HDFS 上提交的文件,根据分片信息生成task(task 的种类可以是Map Task 也可以是Reduce Task )
任务分配阶段
- Application Master向 Resource Manager申请运行task的任务资源
- Resource Manager 将需要运行的Task任务分配给空闲的Node Manager,Node Manager分别领取任务并创建用于执行Task的Container(容器)
任务运行阶段
- Application Master 通知所有接收到task计算任务的Node Manager启动计算
- Node Manager启动Task计算
- 如果这批Task运行完毕后还有新的Task需要执行,则需要向Resource Manager申请Container(容器) 运行新的Task
- 所有的task任务执行完毕后Application Master会向Resource Manager申请注销
作业完成阶段
资源调度器
-
FIFO (先进先出调度器)
它先按照作业的优先级高低,再按照到达时间的先后选择被执行的作业
-
Capacity Scheduler(容量调度器):
支持多个队列,每个队列可配置一定的资源量,每个队列采用FIFO调度策略,为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源量进行限定
-
Fair Scheduler(公平调度器):
同计算能力调度器类似,支持多队列多用户,每个队列中的资源量可以配置,同一队列中的作业公平共享队列中所有资源
YARN通信协议
RPC协议(远程过程调用)