以下内容皆来自于网络,只以学习为目的,不用于任何商业任务
HDFS 系统架构
1、块(Block):将一个文件进行分块,默认大小在Hadoop2.x的版本中是128M,老版本是64M。写入后不能修改,但是可以追加。
2、NameNode 名称节点(NameNode):是master节点,保存整个文件系统的目录信息、文件信息及分块信息,如果主NameNode 失效,切换到Secondary NameNode。处理客户端读写请求。
3、数据节点(DataNode):是slave节点,分布在廉价的计算机上,用于存储Block块文件。
4、客户端(Client):它与namenode进行交互获取文件的位置信息;与datanode交互,读取或写入数据。
5、ScondaryNameNode:并非NameNode的热备,当NameNode挂掉的适合,它并不能马上替换NameNode并提供服务辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode。在紧急情况下,可辅助恢复NameNode
不同分块并行读写操作,提高吞吐量。
NameNode
NameNode管理文件系统的命名空间,它维护着文件系统树及整棵树内所有的文件和目录,即元数据(MetaData)。元数据有三种存储方式:
内存元数据,目的是提升性能,定期从磁盘加载一份镜像到内存中。
命名空间镜像文件(fsImage),保存整个文件系统的目录树。
编辑日志文件(edits),记录文件系统元数据发生的所有更改,如文件的删除或添加等操作信息。
如果NameNode不可用,那么等同于整个HDFS文件系统不可用。如果NameNode由于故障导致磁盘数据丢失,那么等同于整个HDFS文件系统数据丢失。如果NameNode块映射关系的内存爆满,那么等同于整个HDFS文件系统无法再继续存储,也就是意味着NameNode内存决定了HDFS能够存储的块数量。
HDFS 写数据
解释:
比如客户端想上传200m 的一个文件,它首先对文件做一个分块的处理,将200m的文件分成两块,一块大小是128m 另外一块大小是 72m。
接下来客户端创建一个Distributed File System,通过FS模块向 NameNode 请求上传文件,NameNode 检查目标文件是否存在,父目录是否存在。返回是否可以上传。如果可以上传,客户端请求第一个block上传到哪几个Datanode的服务器上。NameNode 检测datanode 信息池,返回可用的3个datanode。这3个datamode是按照网络拓扑排序的,离客户端越近的会有优先级。
接下来客户端通过 FSDataOutputStream 模块与 dn1 建立连接,请求数据传输,并建立Pipeline 管道。在dn1与dn2、dn2 与 dn3之间建立通道。建立管道的意义是说如果没有管道需要上传3次给dn1 dn2 和 dn3。 pipeline 建立完毕后会返回成功信息。
接下来第7步,建立信息传输流,客户端开始往 dn1上传第一个block,以packet 为单位传输数据,大小为 64k。dn1 接收到渊源不断的数据包会复制保存,然后不做拦截,数据包通过pipeline 管道流向dn2,复制保存,再到dn3。
数据保存成功后,客户端会再次请求namenode上传第二个block。
————————————————
版权声明:本文为CSDN博主「蕾欧娜等等」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38746310/article/details/108087122
HDFS读数据
读数据流程相比于写会更简单一些。
客户端依然需要通过 DistributedFilesystem 向NameNode 请求下载文件,NameNode通过查询元数据,找到目标文件块所在的DataNode 地址。并返回给客户端。
客户端会按照就近原则,然后选一台Datanode 服务器,建立连接,请求读取数据。然后DataNode 开始传输数据给客户端(先从磁盘里读取数据输入流,以Packet为单位来做检验)
客户端以packet为单位接收,先在本地缓存,然后写入目标文件。
————————————————
版权声明:本文为CSDN博主「蕾欧娜等等」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38746310/article/details/108087122
SecondaryNameNode介绍
问题产生:NameNode中的元数据存储在内存中,存在断电后,元数据丢失的问题。
解决方案:在磁盘中产生FsImage备份元数据。
新的问题:当在内存中的元数据更新时,若同时更新 FsImage,会让效率降低,不更新会产生不一致问题。
解决方案:引入 Edits 文件(只进行追加操作,效率很高)。每当元数据有更新或添加元数据时,修改内存中的元数据并追加到 Edits 中。当 NameNode 节点断电,可以通过 FsImage 和 Edits 的合并,合并元数据。
新的问题:长时间添加数据到 Edits 中,会导致文件数据过大,效率降低,断电恢复元数据的时间过长。因此需要的定期进行 FsImage 和 Edits 的合并。若由 NameNode 节点来完成该操作,效率又会降低。
解决方案:引入新的节点 SecondaryNameNode,专门用于 FsImage 和 Edits 的合并。
Fsimage: NameNode 内存中元数据序列化后形成的文件。
Edits: 记录客户端更新元数据信息的每一步操作(可通过 Edits 运算出元数据)。
NameNode 启动时,先滚动 Edits 并生成一个空的 edits.inprogress,然后加载 Edits 和 Fsimage 到内存中,此时 NameNode 内存就持有最新的元数据信息。
Client 开始对 NameNode 发送元数据的增删改的请求,这些请求的操作首先会被记录到 edits.inprogress 中(查询元数据 的操作不会被记录在 Edits 中,因为查询操作不会更改元数据信息),如果此时 NameNode 挂掉,重启后会从 Edits 中读取元数据的信息。然后,NameNode 会在内存中执行元数据的增删改的操作。
由于 Edits 中记录的操作会越来越多,Edits 文件会越来越大,导致 NameNode 在启动加载 Edits 时会很慢,所以需要对 Edits 和 Fsimage 进行合并(所谓合并,就是将 Edits 和 Fsimage 加载到内存中,照着 Edits 中的操作一步步执行,最终形成新的 Fsimage)。 SecondaryNameNode 的作用就是帮助 NameNode 进行 Edits 和 Fsimage 的合并工作。
SecondaryNameNode 首先会询问 NameNode 是否需要 CheckPoint(触发 CheckPoint 需要 满足两个条件中的任意一个,定时时间到和 Edits 中数据写满了)。直接带回 NameNode 是否检查结果。SecondaryNameNode 执行 CheckPoint 操作,首先会让 NameNode 滚动 Edits 并生成一个空的 edits.inprogress,滚动 Edits 的目的是给 Edits 打个标记,以后所有新的操 作都写入 edits.inprogress,其他未合并的 Edits 和 Fsimage 会拷贝到 SecondaryNameNode 的本地,然后将拷贝的 Edits 和 Fsimage 加载到内存中进行合并,生成 fsimage.chkpoint, 然后将 fsimage.chkpoint 拷贝给 NameNode,重命名为 Fsimage 后替换掉原来的 Fsimage。 NameNode 在启动时就只需要加载之前未合并的 Edits 和 Fsimage 即可,因为合并过的 Edits 中的元数据信息已经被记录在 Fsimage 中。
————————————————
版权声明:本文为CSDN博主「蕾欧娜等等」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38746310/article/details/108087122
DataNode 工作机制
一个数据块在 DataNode 上以文件形式存储在磁盘上,包括两个文件,一个是数据本 身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。
DataNode 启动后向 NameNode 注册,通过后,周期性(1 小时)的向 NameNode 上 报所有的块信息。
心跳是每 3 秒一次,心跳返回结果带有 NameNode 给该 DataNode 的命令如复制块数 据到另一台机器,或删除某个数据块。如果超过 10 分钟没有收到某个 DataNode 的心跳,则 认为该节点不可用。
集群运行中可以安全加入和退出一些机器。
————————————————
版权声明:本文为CSDN博主「蕾欧娜等等」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38746310/article/details/108087122
HDFS 文件系统高可用性
HDFS的高可用指的是HDFS持续对各类客户端提供读、写服务的能力,因为客户端对HDFS的读、写操作之前都要访问name node服务器,只有从name node获取元数据之后才能继续进行读、写。所以HDFS的高可用的关键在于name node上的元数据持续可用。
在 hadoop 1.x 的 HDFS 框架中只存在一个 namenode 节点,当这个 namenode 节点出现内存溢出、宕机等意外情况之后,整个系统就会停止服务,直到我们重启这个 namenode 节点。为了解决这个问题,在 hadoop2.x 的 HDFS 框架中,实现了 HA 的机制。
在高可用配置下,edit log不再存放在NameNode,而是存放在一个共享存储的地方,这个共享存储由奇数个Journal Node组成,一般是3个节点(JN小集群), 每个JN专门用于存放来自NN的 edit 日志,edit 日志由活跃状态的名称节点写入JN小集群。
解释:
Active NameNode 和 Standby NameNode:两台 NameNode 形成互备,一台处于 Active 状态,为主 NameNode,另外一台处于 Standby 状态,为备 NameNode,只有主 NameNode 才能对外提供读写服务。
主备切换控制器 ZKFailoverController:ZKFailoverController 作为独立的进程运行,对 NameNode 的主备切换进行总体控制。ZKFailoverController 能及时检测到 NameNode 的健康状况,在主 NameNode 故障时借助 Zookeeper 实现自动的主备选举和切换,当然 NameNode 目前也支持不依赖于 Zookeeper 的手动主备切换。
Zookeeper 集群:为主备切换控制器提供主备选举支持。
共享存储系统:共享存储系统是实现 NameNode 的高可用最为关键的部分,共享存储系统保存了 NameNode 在运行过程中所产生的 HDFS 的元数据。Active NameNode 和 Standby NameNode 通过共享存储系统实现元数据同步。在进行主备切换的时候,新的主 NameNode 在确认元数据完全同步之后才能继续对外提供服务。
可以看出,这里的核心是共享存储的实现,下面为大家介绍一种基于 QJM(Quorum Journal Manager)的默认存储方案。方案合并到 HDFS 的 trunk 之中并且作为默认的共享存储实现。
共享存储系统QJM
基于 QJM 的共享存储系统主要用于保存 EditLog,并不保存 FSImage 文件。FSImage 文件还是在 NameNode 的本地磁盘上。
QJM 共享存储的基本思想来自于 Paxos 算法,采用多个称为 JournalNode 的节点组成的 JournalNode 集群来存储 EditLog。每个 JournalNode 保存同样的 EditLog 副本。每次 NameNode 写 EditLog 的时候,除了向本地磁盘写入 EditLog 之外,也会并行地向 JournalNode 集群之中的每一个 JournalNode 发送写请求,只要大多数 (majority) 的 JournalNode 节点返回成功就认为向 JournalNode 集群写入 EditLog 成功。
如果有 2N+1 台 JournalNode,那么根据大多数的原则,最多可以容忍有 N 台 JournalNode 节点挂掉。
Active NameNode 提交 EditLog 到 JournalNode 集群
Standby NameNode 从 JournalNode 集群同步 EditLog
虽然 Active NameNode 向 JournalNode 集群提交 EditLog 是同步的,但 Standby NameNode 采用的是定时从 JournalNode 集群上同步 EditLog 的方式,那么 Standby NameNode 内存中文件系统镜像有很大的可能是落后于 Active NameNode 的,所以 Standby NameNode 在转换为 Active NameNode 的时候需要把落后的 EditLog 补上来。
HDFS 容错机制
HDFS 是具有很好的容错性的分布式存储系统,它利用复制技术实现数据容错能力,数据会被复制多份并存储在集群的不同节点。这样,集群中的某些机器宕机了,数据还可以从其他正常运行的机器获取。如果有一个机器宕机了,HDFS 会在其他可用的机器创建数据的副本,来保证该数据的副本数与集群的副本因子是一致的。
故障类型
我们来看看出现的故障类型。
• 节点失败:即DataNode节点失败。
• 网络故障:无法发送和接收数据。
• 数据损坏:数据在不稳定的网络传输中或在硬盘中存储出错。
故障检测机制
针对这三类故障的检测机制是这样的。
节点失败检测机制
• 每个DataNode以固定的周期向NameNode 发送心跳信号,通过这种方法告诉 NameNode 它们在正常工作。如果在一定的时间内 NameNode 没有收到 DataNode 心跳,就认为该 DataNode 宕机了。
通信故障检测机制
• 只要发送了数据,接收方就会返回确认码。如果经过几次重试之后,还是没有收到确认码,发送方会认为主机挂了或网络发生故障。
数据错误检测机制
• 在传输数据的时候,同时会发送总和检验码,当数据存储到硬盘时,总和检验码也会被存储。
• 所有的 DataNode 都会定期向 NameNode 发送数据块的存储状况。
• 在发送数据块报告前,会先检查总和校验码是否正确,如果数据存在错误就不发送该数据块的信息。
数据块存储故障:数据存储的故障容错,这块主要是磁盘介质,存储数据可能会出现错乱。在DataNode数据块上存储数据时会计算并存储校验和,当对该数据块进行读操作时会计算数据校验和,如果一场就会转而去读其他DataNode节点的备份数据。
DataNode节点故障主要是通过心跳机制,DataNode会定期通过心跳去NameNode保持联系,Namenode监测到DataNode超时没有心跳后,就会查其元数据,通知其他节点复制失效节点上的数据块到其他服务器上,保证副本数量,磁盘故障的话DataNode也是类似处理,DataNode检测到磁盘故障后,将故障块反馈给namenode进行数据块复制。