本文详细的讲解了 HDFS 的架构与原理。

1.Hadoop 架构

Hadoop 由三个模块组成:分布式存储 HDFS、分布式计算 MapReduce、资源调度引擎 Yarn

2.HDFS 体系架构

2.1NameNode

NameNode 负责:文件元数据信息的操作以及处理客户端的请求。NameNode 管理:HDFS 文件系统的命名空间 NameSpace。NameNode 维护:文件系统树(FileSystem)以及文件树中所有的文件和文件夹的元数据信息(matedata)维护文件到块的对应关系和块到节点的对应关系。NameNode 文件:namespace 镜像文件(fsimage),操作日志文件(edit log)这些信息被 Cache 在 RAM 中,当然这两个文件也会被持久化存储在本地硬盘。NameNode 记录:每个文件中各个块所在的数据节点的位置信息。但它并不永久保存块的位置信息,因为这些信息在系统启动时由数据节点重建。从数据节点重建:在 nameNode 启动时,DataNode 向 NameNode 进行注册时发送给 NameNode。

2.1.1 元数据信息

文件名,文件目录结构,文件属性(生成时间,副本数,权限)每个文件的块列表。 以及列表中的块与块所在的 DataNode 之间的地址映射关系 在内存中加载文件系统中每个文件和每个数据块的引用关系(文件、block、datanode 之间的映射信息) 数据会定期保存到本地磁盘,但不保存 block 的位置信息而是由 DataNode 注册时上报和在运行时维护

2.1.2NameNode 文件操作

NameNode 负责文件元数据的操作 ,DataNode 负责处理文件内容的读写请求,数据流不经过 NameNode,会询问它跟那个 DataNode 联系。

2.1.3NameNode 副本

文件数据块到底存放到哪些 DataNode 上,是由 NameNode 决定的,NN 根据全局情况做出放置副本的决定。读取文件的时候,NN 尽量让 client 读取离它最近的 datanode 上的副本,降低带宽消耗和读取时延。

2.1.4NameNode 心跳机制

全权管理数据块的复制,周期性的接受心跳和块的状态报告信息(包含该 DataNode 上所有数据块的列表) 。若接受到心跳信息,NN 认为 DN 工作正常,如果在 10 分钟后还接受到不到 DN 的心跳,那么 NN 认为 DN 已经宕机 这时候 NN 准备要把 DN 上的数据块进行重新的复制。 块的状态报告包含了一个 DN 上所有数据块的列表,blocks report 每个 1 小时发送一次。

2.1.5NameNode 容错机制

没有 Namenode,HDFS 就不能工作。事实上,如果运行 namenode 的机器坏掉的话,系统中的文件将会完全丢失,因为没有其他方法能够将位于不同 datanode 上的文件块(blocks)重建文件。因此,namenode 的容错机制非常重要,Hadoop 提供了两种机制。第一种方式是将持久化存储在本地硬盘的文件系统元数据备份。Hadoop 可以通过配置来让 Namenode 将他的持久化状态文件写到不同的文件系统中。这种写操作是同步并且是原子化的。比较常见的配置是在将持久化状态写到本地硬盘的同时,也写入到一个远程挂载的网络文件系统(NFS)。第二种方式是运行一个辅助的 Namenode(SecondaryNamenode)。 事实上 SecondaryNamenode 并不能被用作 Namenode 它的主要作用是定期的将 Namespace 镜像与操作日志文件(edit log)合并,以防止操作日志文件(edit log)变得过大。通常,SecondaryNamenode 运行在一个单独的物理机上,因为合并操作需要占用大量的 CPU 时间以及和 Namenode 相当的内存。辅助 Namenode 保存着合并后的 Namespace 镜像的一个备份,万一哪天 Namenode 宕机了,这个备份就可以用上了。但是辅助 Namenode 总是落后于主 Namenode,所以在 Namenode 宕机时,数据丢失是不可避免的。在这种情况下,一般的,要结合第一种方式中提到的远程挂载的网络文件系统(NFS)中的 Namenode 的元数据文件来使用,把 NFS 中的 Namenode 元数据文件,拷贝到辅助 Namenode,并把辅助 Namenode 作为主 Namenode 来运行。

2.1.6NameNode 物理结构

Hdfs架构分析与原理详解Hdfs架构分析与原理详解Hdfs架构分析与原理详解

2.1.7NameNode 文件结构

Hdfs架构分析与原理详解NameNode 的存储目录Hdfs架构分析与原理详解

2.2DataNode

一个集群可能包含上千个 DataNode 节点,这些 DataNode 定时和 NameNode 进行通信,接受 NameNode 的指令 为了减轻 NameNode 的负担,NameNode 上并不永久保存哪个 DataNode 上有哪些数据块的信息,而是通过 DataNode 启动时的上报来更新 NameNode 上的映射表。根据客户端或者是 namenode 的调度存储和检索数据,并且定期向 namenode 发送所存储的块(block)的列表,数据块在 DataNode 进程所在的节点上以文件的形式存储在本地磁盘上 ,一个是数据本身 ,一个是元数据(数据块的长度,块数据的校验和,以及时间戳),维护 blockid 与 DataNode 之间的映射信息(元信息)

2.2.1DataNode 工作机制

datanode 启动时,每个 datanode 对本地磁盘进行扫描,将本 datanode 上保存的 block 信息汇报给 namenode namenode 在接收到的 block 信息以及该 block 所在的 datanode 信息等保存在内存中。 DataNode 启动后向 NameNode 注册,通过后周期性(1 小时)的向 NameNode 上报所有的块信息.(1)通过向 NameNode 发送心跳保持与其联系(3 秒一次),心跳返回结果带有 NN 的命令 ,返回的命令为:如块的复制,删除某个数据块…..(2)如果 10 分钟没有收到 DataNode 的心跳,则认为其已经 lost,并 copy 其上的 block 到其它 DataNode(3)DN 在其文件创建后三周进行验证其 checkSum 的值是否和文件创建时的 checkSum 值一致

2.2.2DataNode 读写操作

集群中的每个服务器都运行一个 DataNode 后台程序,这个后台程序负责把 HDFS 数据块读写到本地的文件系统。 当需要通过客户端读/写某个数据时,先由 NameNode 告诉客户端去哪个 DataNode 进行具体的读/写操作 然后,客户端直接与这个 DataNode 服务器上的后台程序进行通信,并且对相关的数据块进行读/写操作。

2.3SecondaryNameNode

SecondaryNameNode 是 HDFS 架构中的一个组成部分,但是经常由于名字而被人误解它真正的用途,其实它真正的用途,是用来保存 namenode 中对 HDFS metadata 的信息的备份,并减少 namenode 重启的时间。对于 hadoop 进程中,要配置好并正确的使用 snn,还是需要做一些工作的。hadoop 的默认配置中让 snn 进程默认运行在了 namenode 的那台机器上,但是这样的话,如果这台机器出错,宕机,对恢复 HDFS 文件系统是很大的灾难,更好的方式是:将 snn 的进程配置在另外一台机器上运行。在 hadoop 中,namenode 负责对 HDFS 的 metadata 的持久化存储,并且处理来自客户端的对 HDFS 的各种操作的交互反馈。为了保证交互速度,HDFS 文件系统的 metadata 是被 load 到 namenode 机器的内存中的,并且会将内存中的这些数据保存到磁盘进行持久化存储。为了保证这个持久化过程不会成为 HDFS 操作的瓶颈,hadoop 采取的方式是:没有对任何一次的当前文件系统的 snapshot 进行持久化,对 HDFS 最近一段时间的操作 list 会被保存到 namenode 中的一个叫 Editlog 的文件中去。当重启 namenode 时,除了 load fslmage 意外,还会对这个 Editlog 文件中记录的 HDFS 操作进行 replay,以恢复 HDFS 重启之前的最终状态。而 SecondaryNameNode,会周期性的将 Editlog 中记录的对 HDFS 的操作合并到一个 checkpoint 中,然后清空 Editlog。所以 namenode 的重启就会 Load 最新的一个 checkpoint,并重现 Editlog 中记录的 hdfs 操作,由于 Editlog 中记录的是从上一次 checkpoint 以后到现在的操作列表,所以就会比较小。如果没有 SecondaryNameNode 的这个周期性的合并过程,那么当每次重启 namenode 的时候,就会花费很长的时间。而这样周期性的合并就能减少重启的时间。同时也能保证 HDFS 系统的完整性。这就是 SecondaryNameNode 所做的事情。所以 snn 并不能分担 namenode 上对 HDFS 交互性操作的压力。尽管如此,当 namenode 机器宕机或者 namenode 进程出问题时,namenode 的 daemon 进程可以通过人工的方式从 snn 上拷贝一份 metadata 来恢复 HDFS 文件系统。至于为什么要将 snn 进程运行在一台非 NameNode 的机器上,这主要出于两点考虑:1、可扩展性:创建一个新的 HDFS 的 snapshot(快照)需要将 namenode 中 load 到内存的 metadata 信息全部拷贝一遍,这样的操作需要的内存和 namenode 占用的内存一样,由于分配给 namenode 进程的内存其实是对 HDFS 文件系统的限制,如果分布式文件系统非常的大,那么 namenode 那台机器的内存就可能会被 namenode 进程全部占据。2、容错性:当 snn 创建一个 checkpoint 的时候,它会将 checkpoint 拷贝成 metadata 的几个拷贝。将这个操作运行到另外一台机器,还可以提供分布式文件系统的容错性。SECONDARYNAMENODE 工作原理

2.3.1SecondaryNameNode 日志与镜像合并步骤

日志与镜像的定期合并总共分五步: 1、SecondaryNameNode 通知 NameNode 准备提交 edits 文件,此时主节点产生 edits.new 2、SecondaryNameNode 通过 http get 方式获取 NameNode 的 fsimage 与 edits 文件(在 SecondaryNameNode 的 current 同级目录下可见到 temp.check-point 或者 previous-checkpoint 目录,这些目录中存储着从 namenode 拷贝来的镜像文件) 3、SecondaryNameNode 开始合并获取的上述两个文件,产生一个新的 fsimage 文件 fsimage.ckpt 4、SecondaryNameNode 用 http post 方式发送 fsimage.ckpt 至 NameNode 5、NameNode 将 fsimage.ckpt 与 edits.new 文件分别重命名为 fsimage 与 edits,然后更新 fstime,整个 checkpoint 过程到此结束。 在新版本的 hadoop 中(hadoop0.21.0),SecondaryNameNode 两个作用被两个节点替换, checkpoint node 与 backup node. SecondaryNameNode 备份由三个参数控制 fs.checkpoint.period 控制周期,fs.checkpoint.size 控制日志文件超过多少大小时合并, dfs.http.address 表示 http 地址,这个参数在 SecondaryNameNode 为单独节点时需要设置。 Hdfs架构分析与原理详解

3.HDFS 机制

3.1 心跳机制

工作原理:

  1. master 启动的时候,会开一个 ipc server 在那里。
  2. slave 启动,连接 master,每隔 3 秒钟向 master 发送一个“心跳”,携带状态信息;
  3. master 通过这个心跳的返回值,向 slave 节点传达指令作用:
  4. Namenode 全权管理数据块的复制,它周期性地从集群中的每个 Datanode 接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该 Datanode 节点工作正常。块状态报告包含了一个该 Datanode 上所有数据块的列表
  5. DataNode 启动后向 NameNode 注册,通过后,周期性(1 小时)的向 NameNode 上报所有的块的列表;每 3 秒向 NamNode 发一次心跳,返回 NameNode 给该 DataNode 的命令;如复制块数据到另一台机器,或删除某个数据块。如果 NameNode 超过 10 分钟没有收 到某个 DataNode 的心跳,则认为该节点不可用。
  6. hadoop 集群刚开始启动时,会进入安全模式(99.9%),就用到了心跳机制

3.2 负载均衡

Hadoop 的 HDFS 集群非常容易出现机器与机器之间磁盘利用率不平衡的情况,例如:当集群内新增、删除节点,或者某个节点机器内硬盘存储达到饱和值。当数据不平衡时,Map 任务可能会分配到没有存储数据的机器,这将导致网络带宽的消耗,也无法很好的进行本地计算。当 HDFS 负载不均衡时,需要对 HDFS 进行数据的负载均衡调整,即对各节点机器上数据的存储分布进行调整。从而,让数据均匀的分布在各个 DataNode 上,均衡 IO 性能,防止热点的发生。进行数据的负载均衡调整,必须要满足如下原则:c(1)数据平衡不能导致数据块减少,数据块备份丢失(2)管理员可以中止数据平衡进程(3)每次移动的数据量以及占用的网络资源,必须是可控的(4)数据均衡过程,不能影响 namenode 的正常工作负载均衡原理如下:Hdfs架构分析与原理详解步骤分析如下:(1)数据均衡服务(Rebalancing Server)首先要求 NameNode 生成 DataNode 数据分布分析报告,获取每个 DataNode 磁盘使用情况(2)Rebalancing Server 汇总需要移动的数据分布情况,计算具体数据块迁移路线图。数据块迁移路线图,确保网络内最短路径(3)开始数据块迁移任务,Proxy Source Data Node 复制一块需要移动数据块(4)将复制的数据块复制到目标 DataNode 上(5)删除原始数据块(6)目标 DataNode 向 Proxy Source Data Node 确认该数据块迁移完成(7)Proxy Source Data Node 向 Rebalancing Server 确认本次数据块迁移完成。然后继续执行这个过程,直至集群达到数据均衡标准

4.HDFS 读写流程

在了解读写过程之前先了了解基本的概念:在 DFSClient 写 HDFS 的过程中,有三个需要搞清楚的单位:block、packet 与 chunk;block 是最大的一个单位,它是最终存储于 DataNode 上的数据粒度,由 dfs.block.size 参数决定,默认是 64M;注:这个参数由客户端配置决定;packet 是中等的一个单位,它是数据由 DFSClient 流向 DataNode 的粒度,以 dfs.write.packet.size 参数为参考值,默认是 64K;注:这个参数为参考值,是指真正在进行数据传输时,会以它为基准进行调整,调整的原因是一个 packet 有特定的结构,调整的目标是这个 packet 的大小刚好包含结构中的所有成员,同时也保证写到 DataNode 后当前 block 的大小不超过设定值;chunk 是最小的一个单位,它是 DFSClient 到 DataNode 数据传输中进行数据校验的粒度,由 io.bytes.per.checksum 参数决定,默认是 512B;注:事实上一个 chunk 还包含 4B 的校验值,因而 chunk 写入 packet 时是 516B;数据与检验值的比值为 128:1,所以对于一个 128M 的 block 会有一个 1M 的校验文件与之对应;

4.1 数据读流程

Hdfs架构分析与原理详解1、客户端调用 FileSystem 实例的 open 方法,获得这个文件对应的输入流 InputStream。2、通过 RPC 远程调用 NameNode ,获得 NameNode 中此文件对应的数据块保存位置,包括这个文件的副本的保存位置( 主要是各 DataNode 的地址) 。3、获得输入流之后,客户端调用 read 方法读取数据。选择最近的 DataNode 建立连接并读取数据。4、如果客户端和其中一个 DataNode 位于同一机器(比如 MapReduce 过程中的 mapper 和 reducer),那么就会直接从本地读取数据。5、到达数据块末端,关闭与这个 DataNode 的连接,然后重新查找下一个数据块。6、不断执行第 2 - 5 步直到数据全部读完。7、客户端调用 close ,关闭输入流 DF S InputStream。在读的过程中如何保证数据的完整性:通过校验和。因为每个 chunk 中都有一个校验位,一个个 chunk 构成 packet,一个个 packet 最终形成 block,故可在 block 上求校验和。HDFS 的 client 端即实现了对 HDFS 文件内容的校验和 (checksum) 检查。当客户端创建一个新的 HDFS 文件时候,分块后会计算这个文件每个数据块的校验和,此校验和会以一个隐藏文件形式保存在同一个 HDFS 命名空间下。当 client 端从 HDFS 中读取文件内容后,它会检查分块时候计算出的校验和(隐藏文件里)和读取到的文件块中校验和是否匹配,如果不匹配,客户端可以选择从其他 Datanode 获取该数据块的副本。

4.2 数据写流程

Hdfs架构分析与原理详解Hdfs架构分析与原理详解1、使用 HDFS 提供的客户端 Client,向远程的 namenode 发起 RPC 请求2、namenode 会检查要创建的文件是否已经存在,创建者是否有权限进行操作,成功则会 为文件创建一个记录,否则会让客户端抛出异常;3、当客户端开始写入文件的时候,客户端会将文件切分成多个 packets,并在内部以数据队列“data queue(数据队列)”的形式管理这些 packets,并向 namenode 申请 blocks,获 取用来存储 replicas 的合适的 datanode 列表,列表的大小根据 namenode 中 replication 的设定而定;4、开始以 pipeline(管道)的形式将 packet 写入所有的 replicas 中。客户端把 packet 以流的 方式写入第一个 datanode,该 datanode 把该 packet 存储之后,再将其传递给在此 pipeline 中的下一个 datanode,直到最后一个 datanode,这种写数据的方式呈流水线的形式。5、最后一个 datanode 成功存储之后会返回一个 ack packet(确认队列),在 pipeline 里传递 至客户端,在客户端的开发库内部维护着"ack queue",成功收到 datanode 返回的 ack packet 后会从"data queue"移除相应的 packet。6、如果传输过程中,有某个 datanode 出现了故障,那么当前的 pipeline 会被关闭,出现故 障的 datanode 会从当前的 pipeline 中移除,剩余的 block 会继续剩下的 datanode 中继续 以 pipeline 的形式传输,同时 namenode 会分配一个新的 datanode,保持 replicas 设定的 数量。7、客户端完成数据的写入后,会对数据流调用 close()方法,关闭数据流;8、只要写入了 dfs.replication.min(最小写入成功的副本数)的复本数(默认为 1),写操作 就会成功,并且这个块可以在集群中异步复制,直到达到其目标复本数(dfs.replication 的默认值为 3),因为 namenode 已经知道文件由哪些块组成,所以它在返回成功前只需 要等待数据块进行最小量的复制。

阅读全文: http://gitbook.cn/gitchat/activity/5e380fe7b140c94fcc3c88cf

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

Hdfs架构分析与原理详解

相关文章: