简述
本文主要基于Hadoop2.x以上版本,用于记录Hadoop组件HDFS的相关知识点。
正文
作为Hadoop 三大组件之一,HDFS主要用于数据存储,而Hadoop又隶属于分布式架构,这就涉及到多服务的数据通信和主备切换,文件备份,文件读写等相关操作。
架构图
各服务介绍
HDFS组件中各个组件相互协调,为分布式高可用服务。
NameNode
- NN保存着HDFS上所有文件的元数据,这些信息以两个文件的形式永久保存在本地磁盘上:fsimage镜像文件和edits编辑日志文件。
- 负责接受客户端的请求
- 负责接收DN上报的信息,给DN分配任务
DataNode
- DN是文件系统的工作结点。它们根据需要来存储并检索数据块(受客户端和NN的调度)
- 定期向NN发送它们所存储的块的列表。(心跳机制)
SecondryNameNode
- 定期合并编辑日志和镜像文件,以防止编辑日志过大。2NN一般在另一条单独的物理计算机上运行,因为需要占用大量CPU时间,并且需要与NN一样多的内存来执行合并操作。
注意:SecondaryNamenode永远无法取代Namenode的位置,也算不上Namenode的一个热备。(热备:在程序运行时进行备份,而它是定期检查合并)
JournalNode
为了使Standby节点保持其状态与Active 节点同步,两个节点都与一组称为"JournalNodes"(JN)的单独守护进程进行通信。当Active 节点执行任何命名空间修改时,它会持久地将修改记录记录到这些JN的大多数中。Standby节点能够从JN读取edit log内容,并不断监视它们以查看edit log内容的更改。当“Standby节点”看到edit log变化时,会将其应用到自己的命名空间。发生故障转移时,备用服务器将确保在将自身升级为活跃状态之前,已从JournalNode读取所有edit log内容。这样可确保在发生故障转移之前,命名空间状态已经完全同步。
JournalNode守护程序相对较轻,因此可以合理地将这些守护程序与其他Hadoop守护程序(例如NameNodes,JobTracker或YARN ResourceManager)并置在计算机上。
注意:必须至少有3个JournalNode守护程序,因为必须将编辑日志修改写入大多数JN。这将允许系统容忍单个计算机的故障。您可能还会运行3个以上的JournalNode,但是为了实际增加系统可以容忍的故障数量,您应该运行奇数个JN(即3、5、7等)。请注意,当与N个JournalNode一起运行时,系统最多可以容忍(N-1)/ 2个故障,并继续正常运行
ZKFC
Failure detector(通过watcher监听机制实现): 及时发现出故障的NN,并通知zkfc
Active node locator: 帮助客户端定位哪个是Active的NN
Mutual exclusion of active state(通过加锁): 保证某一时刻只有一个Active的NN
面试重点
读文件
1)client 向 namenode 发送 RPC 请求。请求文件 block 的位置;
2)namenode 收到请求之后会检查用户权限以及是否有这个文件,如果都符合, 则会视情况返回部分或全部的 block 列表,对于每个 block,NameNode 都会返 回含有该 block 副本的 DataNode 地址列表; 这些返回的 DN 地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 STALE, 这样的排靠后;
3)Client 选取排序靠前的 DataNode 来读取 block,如果客户端本身就是 DataNode,那么将从本地直接获取数据(短路读取特性);
4)底层上本质是建立 Socket Stream(FSDataInputStream),重复的调用父类 DataInputStream 的 read 方法,直到这个块上的数据读取完毕;
5)当读完列表的 block 后,若文件读取还没有结束,客户端会继续向 NameNode 获取下一批的 block 列表
6)读取完一个 block 都会进行 checksum 验证,如果读取 DataNode时出现错 误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的 DataNode 继续读
7)read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回 Client 请求包含块的 DataNode 地址,并不是返回请求块的数据
8) 最终读取来所有的 block 会合并成一个完整的最终文件
写文件
1)client 客户端发送上传请求,通过 RPC 与 namenode 建立通信,namenode 检 查该用户是否有上传权限,以及上传的文件是否在 hdfs 对应的目录下重名,如 果这两者有任意一个不满足,则直接报错,如果两者都满足,则返回给客户端一 个可以上传的信息
2)client 根据文件的大小进行切分,默认 128M 一块,切分完成之后给 namenode 发送请求第一个 block 块上传到哪些服务器上
3)namenode 收到请求之后,根据网络拓扑和机架感知以及副本机制进行文件 分配,返回可用的 DataNode 的地址
机架感知策略:Hadoop在设计时考虑到数据的安全与高效,数据文件默认在HDFS上存放三份,存储策略为:
第一个block副本放在客户端所在的数据节点里(如果客户端不在集群范围内,则从整个集群中随机选择一个合适的数据节点来存放)。
第二个副本放置在与第一个副本所在节点相同机架内的其它数据节点上
第三个副本放置在不同机架的节点上
4)客户端收到地址之后与服务器地址列表中的一个节点如 A 进行通信,本质上 就是 RPC 调用,建立 pipeline,A 收到请求后会继续调用 B,B 在调用 C,将整个 pipeline 建立完成,逐级返回 client
5)client 开始向 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