hdfsgo语言接口 hdfs教程( 四 )


HDFS读取数据使用就近原则,首先寻找相同机架上是否存在副本,其次本地数据中心 , 最后远程数据中心 。
启动时,NameNode进入安全模式,该模式下不会发生数据块复制,NameNode接收来自DataNode的心跳和块报告,每个块都有一个最小副本数量n,数据块在NameNode接受到该块n次后 , 认为这个数据块完成安全复制 。当完成安全复制的数据块比例达到一个可配的百分比值并再过30s后,NameNode退出安全模式,最后判断是否仍然存在未达到最小复制次数的数据块,并对这些块进行复制操作 。
NameNode使用名为EditLog的事务日志持续记录文件系统元数据的每一次改动(如创建文件、改变复制系数) , 使用名为FsImage的文件存储全部的文件系统命名空间(包括块到文件的映射关系和文件系统的相关属性),EditLog和FsImage都存储在NameNode本地文件系统中 。NameNode在内存中保存着元数据和块映射的快照 , 当NameNode启动后或者某个配置项达到阈值时,会从磁盘中读取EditLog和FsImage,通过EditLog新的记录更新内存中的FsImage,再讲新版本的FsImage刷新到磁盘中,然后截断EditLog中已经处理的记录,这个过程就是一个检查点 。检查点的目的是确保文件系统通过在内存中使用元数据的快照从而持续的观察元数据的变更并将快照信息存储到磁盘FsImage中 。检查点通过下面两个配置参数出发,时间周期(dfs.namenode.checkpoint.period)和文件系统事务数量(dfs.namenode.checkpoint.txns),二者同时配置时,满足任意一个条件就会触发检查点 。
所有的HDFS网络协议都是基于TCP/IP的,客户端建立一个到NameNode机器的可配置的TCP端口,用于二者之间的交互 。DataNode使用DataNode协议和NameNode交互 , RPC包装了客户端协议和DataNode协议,通过设计,NameNode不会发起RPC,只负责响应来自客户端或者DataNode的RPC请求 。
HDFS的核心目标是即使在失败或者错误情况下依然能够保证数据可靠性,三种常见失败情况包括NameNode故障、DataNode故障和network partitions 。
网络分区可能会导致部分DataNode市区和NameNode的连接,NameNode通过心跳包判断并将失去连接的DataNode标记为挂掉状态,于是所有注册到挂掉DataNode的数据都不可用了,可能会导致部分数据块的复制数量低于了原本配置的复制系数 。NameNode不断地追踪哪些需要复制的块并在必要时候进行复制 , 触发条件包含多种情况:DataNode不可用、复制乱码、硬件磁盘故障或者认为增大负值系数 。为了避免DataNode的状态不稳定导致的复制风暴,标记DataNode挂掉的超时时间设置比较长(默认10min),用户可以设置更短的时间间隔来标记DataNode为陈旧状态从而避免在对读写性能要求高的请求上使用这些陈旧节点 。
HDFS架构兼容数据各种重新平衡方案,一种方案可以在某个DataNode的空闲空间小于某个阈值时将数据移动到另一个DataNode上;在某个特殊文件突然有高的读取需求时,一种方式是积极创建额外副本并且平衡集群中的其他数据 。这些类型的平衡方案暂时还未实现(不太清楚现有方案是什么...) 。
存储设备、网络或者软件的问题都可能导致从DataNode获取的数据发生乱码,HDFS客户端实现了对文件内容的校验,客户端在创建文件时 , 会计算文件中每个块的校验值并存储到命名空间,当客户端取回数据后会使用校验值对每个块进行校验,如果存在问题,客户端就会去另一个DataNode获取这个块的副本 。
FsImage和EditLog是HDFS的核心数据结构,他们的错误会导致整个HDFS挂掉 , 因此,NameNode应该支持时刻维持FsImage和EditLog的多分复制文件 , 它们的任何改变所有文件应该同步更新 。另一个选择是使用 shared storage on NFS 或者 distributed edit log 支持多个NameNode,官方推荐 distributed edit log。

推荐阅读