
2.2.2 HDFS存储原理
1.写数据过程
第一个副本放置在上传文件的数据节点上;如果是集群外提交,则随机挑选一台磁盘不太满、CPU不太忙的节点。
第二个副本放置在与第一个副本不同的机架的节点上。
第三个副本放置在与第一个副本相同机架的其他节点上。
更多副本放置在随机节点上。
图2.5展示了写数据过程。

图2.5 HDFS写数据过程
代码如下:


2.读数据过程
HDFS提供了一个API可以确定一个数据节点所属的机架ID,客户端也可以调用API获取自己所属的机架ID。
当客户端读取数据时,从名称节点获得数据块不同副本的存放位置列表,列表中包含了副本所在的数据节点,可以调用API来确定客户端和这些数据节点所属的机架ID,当发现某个数据块副本对应的机架ID和客户端对应的机架ID相同时,就优先选择该副本读取数据,如果没有发现,就随机选择一个副本读取数据。图2.6展示了读数据过程。

图2.6 HDFS读数据过程
代码如下:


3.数据出错与恢复
HDFS具有较高的容错性,可以兼容廉价的硬件,它把硬件出错看作一种常态,而不是异常,并设计了相应的机制来检测数据错误和进行自动恢复,主要包括以下几种情形:名称节点出错、数据节点出错和数据出错。
(1)名称节点出错
名称节点保存了所有的元数据信息,其中,最核心的两大数据结构是FsImage和EditLog,如果这两个文件发生损坏,那么整个HDFS实例将失效。因此,HDFS设置了备份机制,把这些核心文件同步复制到备份服务器Secondary NameNode上。当名称节点出错时,就可以根据备份服务器Secondary NameNode中的FsImage和EditLog数据进行恢复。
(2)数据节点出错
每个数据节点会定期向名称节点发送“心跳”信息,向名称节点报告自己的状态。
当数据节点发生故障,或者网络发生断网时,名称节点无法收到来自一些数据节点的心跳信息,这时,这些数据节点就会被标记为“宕机”,节点上面的所有数据都会被标记为“不可读”,名称节点不会再给它们发送任何I/O请求。
这时,有可能出现一种情形,即由于一些数据节点的不可用,会导致一些数据块的副本数量小于冗余因子。
名称节点会定期检查这种情况,一旦发现某个数据块的副本数量小于冗余因子,就会启动数据冗余复制,为它生成新的副本。
HDFS和其他分布式文件系统的最大区别就是可以调整冗余数据的位置。
(3)数据出错
网络传输和磁盘错误等因素,都会造成数据错误。
客户端在读取到数据后,会采用md5和sha1对数据块进行校验,以确定读取到正确的数据。
在文件被创建时,客户端会对每一个文件块进行信息摘录,并把这些信息写入同一个路径的隐藏文件里面。
当客户端读取文件的时候,会先读取该信息文件,然后,利用该信息文件对每个读取的数据块进行校验,如果校验出错,客户端就会请求到另外一个数据节点读取该文件块,并且向名称节点报告这个文件块有错误,名称节点会定期检查并且重新复制这个块。